Improved docker and application config
This commit is contained in:
parent
d63e486499
commit
31562d43cb
19 changed files with 232 additions and 75 deletions
|
@ -100,8 +100,9 @@ ENV GOPATH /go
|
|||
ENV GOBIN $GOPATH/bin
|
||||
ENV PATH $GOBIN:/usr/local/go/bin:$PATH
|
||||
ENV GO111MODULE on
|
||||
ENV NODE_ENV production
|
||||
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" /etc/photoprism /var/photos && chmod -R 777 "$GOPATH"
|
||||
|
||||
# Download InceptionV3 model
|
||||
RUN mkdir -p /model && \
|
||||
|
@ -113,11 +114,13 @@ RUN mkdir -p /model && \
|
|||
WORKDIR "/go/src/github.com/photoprism/photoprism"
|
||||
COPY . .
|
||||
|
||||
RUN cp config.example.yml ~/.photoprism
|
||||
RUN cp config.prod.yml /etc/photoprism/config.yml
|
||||
|
||||
# Build PhotoPrism
|
||||
RUN make dep js install
|
||||
|
||||
RUN cp -r server/assets /etc/photoprism
|
||||
|
||||
# Expose HTTP port
|
||||
EXPOSE 80
|
||||
|
||||
|
|
4
Makefile
4
Makefile
|
@ -15,8 +15,8 @@ install:
|
|||
build:
|
||||
$(GOBUILD) cmd/photoprism/photoprism.go
|
||||
js:
|
||||
(cd frontend && yarn install)
|
||||
(cd frontend && npm run build)
|
||||
(cd frontend && yarn install --prod)
|
||||
(cd frontend && env NODE_ENV=production npm run build)
|
||||
start:
|
||||
$(GORUN) cmd/photoprism/photoprism.go start
|
||||
migrate-db:
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package photoprism
|
||||
|
||||
import (
|
||||
"github.com/gosimple/slug"
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
type Camera struct {
|
||||
gorm.Model
|
||||
CameraSlug string
|
||||
CameraModel string
|
||||
CameraType string
|
||||
CameraNotes string
|
||||
|
@ -16,8 +18,11 @@ func NewCamera(modelName string) *Camera {
|
|||
modelName = "Unknown"
|
||||
}
|
||||
|
||||
cameraSlug := slug.MakeLang(modelName, "en")
|
||||
|
||||
result := &Camera{
|
||||
CameraModel: modelName,
|
||||
CameraSlug: cameraSlug,
|
||||
}
|
||||
|
||||
return result
|
||||
|
|
|
@ -15,7 +15,7 @@ func main() {
|
|||
app := cli.NewApp()
|
||||
app.Name = "PhotoPrism"
|
||||
app.Usage = "Digital Photo Archive"
|
||||
app.Version = "0.2.0"
|
||||
app.Version = "0.0.0"
|
||||
app.Flags = globalCliFlags
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
|
@ -29,12 +29,15 @@ func main() {
|
|||
fmt.Printf("NAME VALUE\n")
|
||||
fmt.Printf("debug %t\n", conf.Debug)
|
||||
fmt.Printf("config-file %s\n", conf.ConfigFile)
|
||||
fmt.Printf("server-ip %s\n", conf.ServerIP)
|
||||
fmt.Printf("server-port %d\n", conf.ServerPort)
|
||||
fmt.Printf("server-mode %s\n", conf.ServerMode)
|
||||
fmt.Printf("server-assets-path %s\n", conf.ServerAssetsPath)
|
||||
fmt.Printf("darktable-cli %s\n", conf.DarktableCli)
|
||||
fmt.Printf("originals-path %s\n", conf.OriginalsPath)
|
||||
fmt.Printf("thumbnails-path %s\n", conf.ThumbnailsPath)
|
||||
fmt.Printf("import-path %s\n", conf.ImportPath)
|
||||
fmt.Printf("export-path %s\n", conf.ExportPath)
|
||||
fmt.Printf("server-assets-path %s\n", conf.ServerAssetsPath)
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -44,17 +47,17 @@ func main() {
|
|||
Usage: "Starts web server",
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{
|
||||
Name: "port, p",
|
||||
Name: "server-port, p",
|
||||
Usage: "HTTP server port",
|
||||
Value: 80,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "ip, i",
|
||||
Name: "server-ip, i",
|
||||
Usage: "HTTP server IP address (optional)",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "mode, m",
|
||||
Name: "server-mode, m",
|
||||
Usage: "debug, release or test",
|
||||
Value: "",
|
||||
},
|
||||
|
@ -64,13 +67,25 @@ func main() {
|
|||
|
||||
conf.SetValuesFromCliContext(context)
|
||||
|
||||
if context.IsSet("server-ip") {
|
||||
conf.ServerIP = context.String("server-ip")
|
||||
}
|
||||
|
||||
if context.IsSet("server-port") {
|
||||
conf.ServerPort = context.Int("server-port")
|
||||
}
|
||||
|
||||
if context.IsSet("server-mode") {
|
||||
conf.ServerMode = context.String("server-mode")
|
||||
}
|
||||
|
||||
conf.CreateDirectories()
|
||||
|
||||
conf.MigrateDb()
|
||||
|
||||
fmt.Printf("Starting web server at port %d...\n", context.Int("port"))
|
||||
|
||||
server.Start(context.String("ip"), context.Int("port"), context.String("mode"), conf)
|
||||
server.Start(conf)
|
||||
|
||||
fmt.Println("Done.")
|
||||
|
||||
|
@ -288,37 +303,37 @@ var globalCliFlags = []cli.Flag{
|
|||
cli.StringFlag{
|
||||
Name: "config-file, c",
|
||||
Usage: "config filename",
|
||||
Value: "~/.photoprism",
|
||||
Value: "/etc/photoprism/config.yml",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "darktable-cli",
|
||||
Usage: "darktable CLI",
|
||||
Value: "/Applications/darktable.app/Contents/MacOS/darktable-cli",
|
||||
Value: "/usr/bin/darktable-cli",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "originals-path",
|
||||
Usage: "originals path",
|
||||
Value: "~/Photos/Originals",
|
||||
Value: "/var/photoprism/originals",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "thumbnails-path",
|
||||
Usage: "thumbnails path",
|
||||
Value: "~/Photos/Thumbnails",
|
||||
Value: "/var/photoprism/thumbnails",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "import-path",
|
||||
Usage: "import path",
|
||||
Value: "~/Photos/Import",
|
||||
Value: "/var/photoprism/import",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "export-path",
|
||||
Usage: "export path",
|
||||
Value: "~/Photos/Export",
|
||||
Value: "/var/photoprism/export",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "server-assets-path",
|
||||
Usage: "server assets path for templates, js and css",
|
||||
Value: "~/Photos/Server",
|
||||
Value: "/var/photoprism/server",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "database-driver",
|
||||
|
@ -328,6 +343,6 @@ var globalCliFlags = []cli.Flag{
|
|||
cli.StringFlag{
|
||||
Name: "database-dsn",
|
||||
Usage: "database data source name (DSN)",
|
||||
Value: "photoprism:photoprism@tcp(database:3306)/photoprism",
|
||||
Value: "photoprism:photoprism@tcp(localhost:3306)/photoprism",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
debug: true
|
||||
darktable-cli: /usr/bin/darktable-cli
|
||||
originals-path: photos/originals
|
||||
thumbnails-path: photos/thumbnails
|
||||
import-path: photos/import
|
||||
export-path: photos/export
|
||||
server-ip:
|
||||
server-mode: debug
|
||||
server-port: 80
|
||||
server-assets-path: server/assets
|
||||
database-driver: mysql
|
||||
database-dsn: photoprism:photoprism@tcp(database:3306)/photoprism?parseTime=true
|
57
config.go
57
config.go
|
@ -17,12 +17,15 @@ import (
|
|||
type Config struct {
|
||||
Debug bool
|
||||
ConfigFile string
|
||||
ServerIP string
|
||||
ServerPort int
|
||||
ServerMode string
|
||||
ServerAssetsPath string
|
||||
DarktableCli string
|
||||
OriginalsPath string
|
||||
ThumbnailsPath string
|
||||
ImportPath string
|
||||
ExportPath string
|
||||
ServerAssetsPath string
|
||||
DatabaseDriver string
|
||||
DatabaseDsn string
|
||||
db *gorm.DB
|
||||
|
@ -43,43 +46,61 @@ func (c *Config) SetValuesFromFile(fileName string) error {
|
|||
|
||||
c.ConfigFile = fileName
|
||||
|
||||
if OriginalsPath, err := yamlConfig.Get("originals-path"); err == nil {
|
||||
c.OriginalsPath = GetExpandedFilename(OriginalsPath)
|
||||
if debug, err := yamlConfig.GetBool("debug"); err == nil {
|
||||
c.Debug = debug
|
||||
}
|
||||
|
||||
if ThumbnailsPath, err := yamlConfig.Get("thumbnails-path"); err == nil {
|
||||
c.ThumbnailsPath = GetExpandedFilename(ThumbnailsPath)
|
||||
if serverIP, err := yamlConfig.Get("server-ip"); err == nil {
|
||||
c.ServerIP = serverIP
|
||||
}
|
||||
|
||||
if ImportPath, err := yamlConfig.Get("import-path"); err == nil {
|
||||
c.ImportPath = GetExpandedFilename(ImportPath)
|
||||
if serverPort, err := yamlConfig.GetInt("server-port"); err == nil {
|
||||
c.ServerPort = int(serverPort)
|
||||
}
|
||||
|
||||
if ExportPath, err := yamlConfig.Get("export-path"); err == nil {
|
||||
c.ExportPath = GetExpandedFilename(ExportPath)
|
||||
if serverMode, err := yamlConfig.Get("server-mode"); err == nil {
|
||||
c.ServerMode = serverMode
|
||||
}
|
||||
|
||||
if ServerAssetsPath, err := yamlConfig.Get("server-assets-path"); err == nil {
|
||||
c.ServerAssetsPath = GetExpandedFilename(ServerAssetsPath)
|
||||
if serverAssetsPath, err := yamlConfig.Get("server-assets-path"); err == nil {
|
||||
c.ServerAssetsPath = GetExpandedFilename(serverAssetsPath)
|
||||
}
|
||||
|
||||
if DarktableCli, err := yamlConfig.Get("darktable-cli"); err == nil {
|
||||
c.DarktableCli = GetExpandedFilename(DarktableCli)
|
||||
if originalsPath, err := yamlConfig.Get("originals-path"); err == nil {
|
||||
c.OriginalsPath = GetExpandedFilename(originalsPath)
|
||||
}
|
||||
|
||||
if DatabaseDriver, err := yamlConfig.Get("database-driver"); err == nil {
|
||||
c.DatabaseDriver = DatabaseDriver
|
||||
if thumbnailsPath, err := yamlConfig.Get("thumbnails-path"); err == nil {
|
||||
c.ThumbnailsPath = GetExpandedFilename(thumbnailsPath)
|
||||
}
|
||||
|
||||
if DatabaseDsn, err := yamlConfig.Get("database-dsn"); err == nil {
|
||||
c.DatabaseDsn = DatabaseDsn
|
||||
if importPath, err := yamlConfig.Get("import-path"); err == nil {
|
||||
c.ImportPath = GetExpandedFilename(importPath)
|
||||
}
|
||||
|
||||
if exportPath, err := yamlConfig.Get("export-path"); err == nil {
|
||||
c.ExportPath = GetExpandedFilename(exportPath)
|
||||
}
|
||||
|
||||
if darktableCli, err := yamlConfig.Get("darktable-cli"); err == nil {
|
||||
c.DarktableCli = GetExpandedFilename(darktableCli)
|
||||
}
|
||||
|
||||
if databaseDriver, err := yamlConfig.Get("database-driver"); err == nil {
|
||||
c.DatabaseDriver = databaseDriver
|
||||
}
|
||||
|
||||
if databaseDsn, err := yamlConfig.Get("database-dsn"); err == nil {
|
||||
c.DatabaseDsn = databaseDsn
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) SetValuesFromCliContext(context *cli.Context) error {
|
||||
c.Debug = context.GlobalBool("debug")
|
||||
if context.GlobalBool("debug") {
|
||||
c.Debug = context.GlobalBool("debug")
|
||||
}
|
||||
|
||||
if context.GlobalIsSet("originals-path") {
|
||||
c.OriginalsPath = GetExpandedFilename(context.GlobalString("originals-path"))
|
||||
|
|
12
config.osx.yml
Normal file
12
config.osx.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
debug: false
|
||||
darktable-cli: /Applications/darktable.app/Contents/MacOS/darktable-cli
|
||||
originals-path: ~/Photos/Originals
|
||||
thumbnails-path: ~/Photos/Thumbnails
|
||||
import-path: ~/Photos/Import
|
||||
export-path: ~/Photos/Export
|
||||
server-ip:
|
||||
server-mode: release
|
||||
server-port: 8080
|
||||
server-assets-path: ~/Photos/Server
|
||||
database-driver: mysql
|
||||
database-dsn: photoprism:photoprism@tcp(localhost:3306)/photoprism?parseTime=true
|
12
config.prod.yml
Normal file
12
config.prod.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
debug: false
|
||||
darktable-cli: /usr/bin/darktable-cli
|
||||
originals-path: /var/photos/originals
|
||||
thumbnails-path: /var/photos/thumbnails
|
||||
import-path: /var/photos/import
|
||||
export-path: /var/photos/export
|
||||
server-ip:
|
||||
server-mode: release
|
||||
server-port: 80
|
||||
server-assets-path: /etc/photoprism/assets
|
||||
database-driver: mysql
|
||||
database-dsn: photoprism:photoprism@tcp(database:3306)/photoprism?parseTime=true
|
|
@ -87,7 +87,7 @@ func TestNewConfig(t *testing.T) {
|
|||
func TestConfig_SetValuesFromFile(t *testing.T) {
|
||||
c := NewConfig()
|
||||
|
||||
c.SetValuesFromFile(GetExpandedFilename("config.example.yml"))
|
||||
c.SetValuesFromFile(GetExpandedFilename("config.dev.yml"))
|
||||
|
||||
assert.Equal(t, GetExpandedFilename("photos/originals"), c.OriginalsPath)
|
||||
assert.Equal(t, GetExpandedFilename("photos/thumbnails"), c.ThumbnailsPath)
|
||||
|
|
26
docker-compose.prod.yml
Normal file
26
docker-compose.prod.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
version: '3.3'
|
||||
|
||||
services:
|
||||
photoprism:
|
||||
build: .
|
||||
ports:
|
||||
- 80:80
|
||||
volumes:
|
||||
- photo-data:/var/photos
|
||||
|
||||
database:
|
||||
image: mysql:latest
|
||||
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=1024
|
||||
volumes:
|
||||
- database-data:/var/lib/mysql
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: photoprism
|
||||
MYSQL_USER: photoprism
|
||||
MYSQL_PASSWORD: photoprism
|
||||
MYSQL_DATABASE: photoprism
|
||||
|
||||
volumes:
|
||||
photo-data:
|
||||
driver: local
|
||||
database-data:
|
||||
driver: local
|
|
@ -8,6 +8,7 @@ services:
|
|||
- 80:80
|
||||
volumes:
|
||||
- .:/go/src/github.com/photoprism/photoprism
|
||||
- ./config.dev.yml:/etc/photoprism/config.yml
|
||||
|
||||
database:
|
||||
image: mysql:latest
|
||||
|
|
|
@ -23,13 +23,14 @@ Vue.prototype.$config = config;
|
|||
|
||||
Vue.use(Vuetify, {
|
||||
theme: {
|
||||
primary: '#FDD835',
|
||||
primary: '#FFD600',
|
||||
secondary: '#b0bec5',
|
||||
accent: '#8c9eff',
|
||||
error: '#F44336',
|
||||
error: '#E57373',
|
||||
info: '#00B8D4',
|
||||
success: '#00BFA5',
|
||||
warning: '#FFD600',
|
||||
delete: '#E57373',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
label="Camera"
|
||||
flat solo
|
||||
color="blue-grey"
|
||||
item-value="ID"
|
||||
item-text="CameraModel"
|
||||
v-model="query.camera_id"
|
||||
:items="options.cameras">
|
||||
</v-select>
|
||||
|
@ -121,7 +123,7 @@
|
|||
fab
|
||||
dark
|
||||
small
|
||||
color="red"
|
||||
color="delete"
|
||||
>
|
||||
<v-icon>delete</v-icon>
|
||||
</v-btn>
|
||||
|
@ -190,16 +192,11 @@
|
|||
const resultCount = query.hasOwnProperty('count') ? parseInt(query['count']) : 60;
|
||||
const resultPage = query.hasOwnProperty('page') ? parseInt(query['page']) : 1;
|
||||
const resultOffset = resultCount * (resultPage - 1);
|
||||
const order = query.hasOwnProperty('order') && query['order'] != "" ? query['order'] : 'taken_at DESC';
|
||||
const camera_id = query.hasOwnProperty('camera_id') ? parseInt(query['camera_id']) : '';
|
||||
const order = query['order'] ? query['order'] : 'taken_at DESC';
|
||||
const camera_id = query['camera_id'] ? parseInt(query['camera_id']) : 0;
|
||||
const q = query.hasOwnProperty('q') ? query['q'] : '';
|
||||
const view = query.hasOwnProperty('view') ? query['view'] : 'tile';
|
||||
const cameras = [{value: '', text: 'All Cameras'}];
|
||||
|
||||
console.log(this.$config.getValue('cameras'));
|
||||
this.$config.getValue('cameras').forEach(function (camera) {
|
||||
cameras.push({value: camera.ID, text: camera.CameraModel});
|
||||
});
|
||||
const cameras = [{ID: 0, CameraModel: 'All Cameras'}].concat( this.$config.getValue('cameras'));
|
||||
|
||||
return {
|
||||
'snackbarVisible': false,
|
||||
|
@ -329,7 +326,7 @@
|
|||
this.resultCount = parseInt(response.headers['x-result-count']);
|
||||
this.resultOffset = parseInt(response.headers['x-result-offset']);
|
||||
this.results = response.models;
|
||||
this.$alert.info(this.results.length + ' photos found');
|
||||
this.$alert.info(this.resultTotal + ' photos found');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2,6 +2,8 @@ const path = require('path');
|
|||
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
const webpack = require('webpack');
|
||||
|
||||
const PATHS = {
|
||||
app: path.join(__dirname, 'src/app.js'),
|
||||
css: path.join(__dirname, 'css'),
|
||||
|
@ -16,6 +18,7 @@ const cssPlugin = new ExtractTextPlugin({
|
|||
process.noDeprecation = true;
|
||||
|
||||
const config = {
|
||||
devtool: false,
|
||||
entry: {
|
||||
app: PATHS.app,
|
||||
},
|
||||
|
@ -33,7 +36,7 @@ const config = {
|
|||
},
|
||||
},
|
||||
plugins: [
|
||||
cssPlugin,
|
||||
cssPlugin
|
||||
],
|
||||
node: {
|
||||
fs: 'empty',
|
||||
|
@ -100,8 +103,12 @@ const config = {
|
|||
};
|
||||
|
||||
// No sourcemap for production
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
config.devtool = "";
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
const devToolPlugin = new webpack.SourceMapDevToolPlugin({
|
||||
filename: '[name].map',
|
||||
});
|
||||
|
||||
config.plugins.push(devToolPlugin);
|
||||
}
|
||||
|
||||
module.exports = config;
|
22
search.go
22
search.go
|
@ -12,6 +12,10 @@ type Search struct {
|
|||
db *gorm.DB
|
||||
}
|
||||
|
||||
type SearchCount struct {
|
||||
Total int
|
||||
}
|
||||
|
||||
type PhotoSearchResult struct {
|
||||
// Photo
|
||||
ID uint
|
||||
|
@ -72,11 +76,10 @@ func NewSearch(originalsPath string, db *gorm.DB) *Search {
|
|||
return instance
|
||||
}
|
||||
|
||||
func (s *Search) Photos(form forms.PhotoSearchForm) ([]PhotoSearchResult, error) {
|
||||
q := s.db.Preload("Tags").Preload("Files").Preload("Location").Preload("Albums")
|
||||
|
||||
func (s *Search) Photos(form forms.PhotoSearchForm) ([]PhotoSearchResult, int, error) {
|
||||
q := s.db.NewScope(nil).DB()
|
||||
q = q.Table("photos").
|
||||
Select(`photos.*,
|
||||
Select(`SQL_CALC_FOUND_ROWS photos.*,
|
||||
files.id AS file_id, files.file_name, files.file_type, files.file_mime, files.file_width, files.file_height, files.file_aspect_ratio, files.file_orientation,
|
||||
cameras.camera_model,
|
||||
locations.loc_display_name, locations.loc_name, locations.loc_city, locations.loc_postcode, locations.loc_country, locations.loc_country_code, locations.loc_category, locations.loc_type,
|
||||
|
@ -90,7 +93,7 @@ func (s *Search) Photos(form forms.PhotoSearchForm) ([]PhotoSearchResult, error)
|
|||
Group("photos.id, files.id")
|
||||
|
||||
if form.Query != "" {
|
||||
q = q.Where("tags.tag_label LIKE ? OR MATCH (photo_title, photo_description, photo_artist, photo_colors) AGAINST (?)", strings.ToLower(form.Query)+"%", form.Query)
|
||||
q = q.Where("tags.tag_label LIKE ? OR MATCH (photo_title, photo_description, photo_artist, photo_colors) AGAINST (?)", "%"+strings.ToLower(form.Query)+"%", form.Query)
|
||||
}
|
||||
|
||||
if form.CameraID > 0 {
|
||||
|
@ -104,7 +107,7 @@ func (s *Search) Photos(form forms.PhotoSearchForm) ([]PhotoSearchResult, error)
|
|||
rows, err := q.Rows()
|
||||
|
||||
if err != nil {
|
||||
return results, err
|
||||
return results, 0, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
@ -115,7 +118,12 @@ func (s *Search) Photos(form forms.PhotoSearchForm) ([]PhotoSearchResult, error)
|
|||
results = append(results, result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
// TODO: Check if this works properly with concurrent requests and caching
|
||||
count := &SearchCount{}
|
||||
s.db.Raw("SELECT FOUND_ROWS() AS total").Scan(&count)
|
||||
total := count.Total
|
||||
|
||||
return results, total, nil
|
||||
}
|
||||
|
||||
func (s *Search) FindFiles(count int, offset int) (files []File) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestSearch_Photos(t *testing.T) {
|
||||
func TestSearch_Photos_Query(t *testing.T) {
|
||||
conf := NewTestConfig()
|
||||
|
||||
conf.CreateDirectories()
|
||||
|
@ -16,15 +16,52 @@ func TestSearch_Photos(t *testing.T) {
|
|||
|
||||
var form forms.PhotoSearchForm
|
||||
|
||||
form.Query = "elephant"
|
||||
form.Query = "african"
|
||||
form.Count = 3
|
||||
form.Offset = 0
|
||||
|
||||
photos, err := search.Photos(form)
|
||||
photos, total, err := search.Photos(form)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(photos)
|
||||
t.Logf("Total Count: %d", total)
|
||||
|
||||
photos, total, err = search.Photos(form)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(photos)
|
||||
t.Logf("Total Count: %d", total)
|
||||
|
||||
}
|
||||
|
||||
func TestSearch_Photos_Camera(t *testing.T) {
|
||||
conf := NewTestConfig()
|
||||
|
||||
conf.CreateDirectories()
|
||||
|
||||
conf.InitializeTestData(t)
|
||||
|
||||
search := NewSearch(conf.OriginalsPath, conf.GetDb())
|
||||
|
||||
var form forms.PhotoSearchForm
|
||||
|
||||
form.Query = ""
|
||||
form.CameraID = 2
|
||||
form.Count = 3
|
||||
form.Offset = 0
|
||||
|
||||
photos, total, err := search.Photos(form)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Log(photos)
|
||||
t.Logf("Total Count: %d", total)
|
||||
}
|
|
@ -28,15 +28,17 @@ func ConfigureRoutes(app *gin.Engine, conf *photoprism.Config) {
|
|||
|
||||
c.MustBindWith(&form, binding.Form)
|
||||
|
||||
if photos, err := search.Photos(form); err == nil {
|
||||
c.Header("x-result-total", strconv.Itoa(len(photos)))
|
||||
c.Header("x-result-count", strconv.Itoa(form.Count))
|
||||
c.Header("x-result-offset", strconv.Itoa(form.Offset))
|
||||
result, total, err := search.Photos(form)
|
||||
|
||||
c.JSON(http.StatusOK, photos)
|
||||
} else {
|
||||
c.AbortWithError(400, err)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(400, gin.H{"error": err.Error()})
|
||||
}
|
||||
|
||||
c.Header("x-result-total", strconv.Itoa(total))
|
||||
c.Header("x-result-count", strconv.Itoa(form.Count))
|
||||
c.Header("x-result-offset", strconv.Itoa(form.Offset))
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
})
|
||||
|
||||
// v1.OPTIONS()
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"github.com/photoprism/photoprism"
|
||||
)
|
||||
|
||||
func Start(address string, port int, mode string, conf *photoprism.Config) {
|
||||
if mode != "" {
|
||||
gin.SetMode(mode)
|
||||
func Start(conf *photoprism.Config) {
|
||||
if conf.ServerMode != "" {
|
||||
gin.SetMode(conf.ServerMode)
|
||||
} else if conf.Debug == false{
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
@ -17,5 +17,5 @@ func Start(address string, port int, mode string, conf *photoprism.Config) {
|
|||
|
||||
ConfigureRoutes(app, conf)
|
||||
|
||||
app.Run(fmt.Sprintf("%s:%d", address, port))
|
||||
app.Run(fmt.Sprintf("%s:%d", conf.ServerIP, conf.ServerPort))
|
||||
}
|
||||
|
|
10
util.go
10
util.go
|
@ -35,9 +35,15 @@ func getRandomInt(min, max int) int {
|
|||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
_, err := os.Stat(filename)
|
||||
info, err := os.Stat(filename)
|
||||
|
||||
return err == nil
|
||||
return err == nil && !info.IsDir()
|
||||
}
|
||||
|
||||
func pathExists(pathname string) bool {
|
||||
info, err := os.Stat(pathname)
|
||||
|
||||
return err == nil && info.IsDir()
|
||||
}
|
||||
|
||||
func fileHash(filename string) string {
|
||||
|
|
Loading…
Reference in a new issue