Implemented navigation
This commit is contained in:
parent
fcddb5ddfe
commit
04fb039ab6
20 changed files with 331 additions and 90 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -36,5 +36,6 @@ Thumbs.db
|
|||
.settings
|
||||
.swp
|
||||
.tmp
|
||||
/photos/
|
||||
/vendor/
|
||||
node_modules/
|
|
@ -1,4 +1,4 @@
|
|||
darktable-cli: /Applications/darktable.app/Contents/MacOS/darktable-cli
|
||||
darktable-cli: /usr/bin/darktable-cli
|
||||
originals-path: photos/originals
|
||||
thumbnails-path: photos/thumbnails
|
||||
import-path: photos/import
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
#alerts {
|
||||
position: fixed;
|
||||
z-index: 1051;
|
||||
left: 20%;
|
||||
top: 10px;
|
||||
right: 20%;
|
||||
top: 50px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: auto;
|
||||
display: block;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#alerts .success {
|
||||
background-color: #71D774;
|
||||
background-color: #c8e5ff;
|
||||
}
|
||||
|
||||
#alerts .success:after {
|
||||
}
|
||||
|
||||
#alerts .error {
|
||||
background-color: #FF5A5A;
|
||||
background-color: #ffcaca;
|
||||
}
|
||||
|
||||
#alerts .error:before {
|
||||
}
|
||||
|
||||
#alerts .warning {
|
||||
background-color: #FCBD39;
|
||||
background-color: #ffedc1;
|
||||
}
|
||||
|
||||
#alerts .warning:before {
|
||||
}
|
||||
|
||||
#alerts .info {
|
||||
color: #49AFF5;
|
||||
background-color: #49AFF5;
|
||||
background-color: #feffb8;
|
||||
}
|
||||
|
||||
#alerts .alert {
|
||||
color: #FFF;
|
||||
color: #333;
|
||||
display: block;
|
||||
left: 0;
|
||||
right: 0;
|
||||
min-height: 14px;
|
||||
padding: 8px 10px 8px 10px;
|
||||
font-size: 14px;
|
||||
min-height: 13px;
|
||||
padding: 4px 10px 4px 10px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
opacity: 1;
|
||||
border-radius: 0;
|
||||
border-radius: 0px;
|
||||
margin: 1px 0 0 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,36 +19,66 @@
|
|||
background-color: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
body {
|
||||
background: #333333;
|
||||
color: rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 10px 20px;
|
||||
}
|
||||
/*
|
||||
nav {
|
||||
background-color: #616161;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav a:hover {
|
||||
text-decoration: none !important;
|
||||
color: rgba(255, 255, 255, .87) !important;
|
||||
main div.page {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
nav a {
|
||||
font-size: 14px;
|
||||
font-weight: bold !important;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 120px;
|
||||
background: #616161;
|
||||
padding: 10px;
|
||||
text-decoration: none;
|
||||
border-bottom: 3px solid #616161;
|
||||
color: rgba(255, 255, 255, .54) !important;
|
||||
.navbar {
|
||||
padding: 3px 2rem 3px 2rem;
|
||||
background: black !important;
|
||||
}
|
||||
|
||||
nav a.router-link-active {
|
||||
font-weight: bold !important;
|
||||
border-bottom: 3px solid #E64A19;
|
||||
color: rgba(255, 255, 255, .87) !important;
|
||||
}*/
|
||||
.navbar .nav-item-photos .nav-link.active,
|
||||
.navbar .nav-item-photos .nav-link:hover {
|
||||
color: #c8e5ff;
|
||||
}
|
||||
|
||||
main div.page-photos {
|
||||
border-top: 2px solid #c8e5ff;
|
||||
}
|
||||
|
||||
.navbar .nav-item-albums .nav-link.active,
|
||||
.navbar .nav-item-albums .nav-link:hover {
|
||||
color: #c4ffcb;
|
||||
}
|
||||
|
||||
main div.page-albums {
|
||||
border-top: 2px solid #c4ffcb;
|
||||
}
|
||||
|
||||
.navbar .nav-item-import .nav-link.active,
|
||||
.navbar .nav-item-import .nav-link:hover {
|
||||
color: #feffb8;
|
||||
}
|
||||
|
||||
main div.page-import {
|
||||
border-top: 2px solid #feffb8;
|
||||
}
|
||||
|
||||
.navbar .nav-item-export .nav-link.active,
|
||||
.navbar .nav-item-export .nav-link:hover {
|
||||
color: #ffedc1;
|
||||
}
|
||||
|
||||
main div.page-export {
|
||||
border-top: 2px solid #ffedc1;
|
||||
}
|
||||
|
||||
.navbar .nav-item-settings .nav-link.active,
|
||||
.navbar .nav-item-settings .nav-link:hover {
|
||||
color: #f5c5c5;
|
||||
}
|
||||
|
||||
main div.page-settings {
|
||||
border-top: 2px solid #f5c5c5;
|
||||
}
|
|
@ -15,7 +15,9 @@
|
|||
"axios-mock-adapter": "^1.8.1",
|
||||
"chart.js": "^2.5.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"justified-gallery": "^0.1.0",
|
||||
"vue": "^2.4.4",
|
||||
"vue-justified-layout": "^0.1.0",
|
||||
"vue-router": "^2.7.0",
|
||||
"vue-template-compiler": "^2.4.4"
|
||||
},
|
||||
|
@ -31,16 +33,14 @@
|
|||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-register": "^6.22.0",
|
||||
"bootstrap-vue": "^2.0.0-rc.11",
|
||||
"bootstrap": "^4.1.3",
|
||||
"bootstrap-vue": "^2.0.0-rc.11",
|
||||
"chai": "^3.5.0",
|
||||
"chalk": "^1.1.3",
|
||||
"connect-history-api-fallback": "^1.3.0",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"cross-env": "^3.1.4",
|
||||
"css-loader": "^0.28.11",
|
||||
"node-sass": "^4.9.2",
|
||||
"sass-loader": "^7.0.3",
|
||||
"eslint": "^3.14.1",
|
||||
"eslint-config-standard": "^6.2.1",
|
||||
"eslint-friendly-formatter": "^2.0.7",
|
||||
|
@ -65,11 +65,13 @@
|
|||
"karma-webpack": "^2.0.3",
|
||||
"lodash": "^4.17.4",
|
||||
"mocha": "^3.3.0",
|
||||
"node-sass": "^4.9.2",
|
||||
"optimize-css-assets-webpack-plugin": "^1.3.0",
|
||||
"ora": "^1.1.0",
|
||||
"phantomjs-prebuilt": "^2.1.14",
|
||||
"pluralize": "^4.0.0",
|
||||
"pubsub-js": "^1.5.6",
|
||||
"sass-loader": "^7.0.3",
|
||||
"style-loader": "^0.16.1",
|
||||
"svg-url-loader": "^2.0.2",
|
||||
"url-loader": "^0.5.8",
|
||||
|
@ -91,4 +93,4 @@
|
|||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
36
frontend/src/app/pages/albums.vue
Normal file
36
frontend/src/app/pages/albums.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="page page-albums">
|
||||
<h1 class="md-display-1">Albums</h1>
|
||||
<p class="md-subheading">
|
||||
A user-friendly tool for importing, filtering and archiving large amounts of JPEG and RAW files
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'browse',
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
36
frontend/src/app/pages/export.vue
Normal file
36
frontend/src/app/pages/export.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="page page-export">
|
||||
<h1 class="md-display-1">Export</h1>
|
||||
<p class="md-subheading">
|
||||
A user-friendly tool for importing, filtering and archiving large amounts of JPEG and RAW files
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'browse',
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
36
frontend/src/app/pages/import.vue
Normal file
36
frontend/src/app/pages/import.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="page page-import">
|
||||
<h1>Import</h1>
|
||||
<p class="md-subheading">
|
||||
A user-friendly tool for importing, filtering and archiving large amounts of JPEG and RAW files
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'import',
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
|
@ -1,7 +1,5 @@
|
|||
<template>
|
||||
|
||||
|
||||
<div class="dashboard">
|
||||
<div class="page page-photos">
|
||||
<h1 class="md-display-1">Welcome to PhotoPrism</h1>
|
||||
<p class="md-subheading">
|
||||
A user-friendly tool for importing, filtering and archiving large amounts of JPEG and RAW files
|
||||
|
@ -11,25 +9,12 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
name: 'photos',
|
||||
data() {
|
||||
return {
|
||||
msg: 'Welcome to PhotoPrism',
|
||||
username: this.$session.getFullName(),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.snackbar.open();
|
||||
},
|
||||
|
||||
showNotification() {
|
||||
this.$alert.success('Yeah wuwuwu');
|
||||
},
|
||||
|
||||
logout() {
|
||||
this.$session.logout();
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
52
frontend/src/app/pages/settings.vue
Normal file
52
frontend/src/app/pages/settings.vue
Normal file
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<div class="page page-settings">
|
||||
<h1 class="md-display-1">Settings</h1>
|
||||
<p class="md-subheading">
|
||||
|
||||
</p>
|
||||
<button v-on:click="showSuccess()">Show Success</button>
|
||||
<button v-on:click="showInfo()">Show Info</button>
|
||||
<button v-on:click="showError()">Show Error</button>
|
||||
<button v-on:click="showWarning()">Show Warning</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showSuccess() {
|
||||
this.$alert.success('Action successfully completed');
|
||||
},
|
||||
showInfo() {
|
||||
this.$alert.info('This is an info');
|
||||
},
|
||||
showError() {
|
||||
this.$alert.error('An error has occurred - please check logs');
|
||||
},
|
||||
showWarning() {
|
||||
this.$alert.warning('This is a warning');
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
</style>
|
|
@ -1,7 +1,15 @@
|
|||
import Welcome from 'app/pages/welcome.vue';
|
||||
import Photos from 'app/pages/photos.vue';
|
||||
import Albums from 'app/pages/albums.vue';
|
||||
import Import from 'app/pages/Import.vue';
|
||||
import Export from 'app/pages/Export.vue';
|
||||
import Settings from 'app/pages/settings.vue';
|
||||
|
||||
export default [
|
||||
{ path: '/', redirect: '/welcome' },
|
||||
{ path: '/welcome', component: Welcome },
|
||||
{ path: '*', redirect: '/welcome' },
|
||||
{ path: '/', redirect: '/photos' },
|
||||
{ path: '/photos', component: Photos },
|
||||
{ path: '/albums', component: Albums },
|
||||
{ path: '/import', component: Import },
|
||||
{ path: '/export', component: Export },
|
||||
{ path: '/settings', component: Settings },
|
||||
{ path: '*', redirect: '/photos' },
|
||||
];
|
||||
|
|
|
@ -4,14 +4,16 @@
|
|||
|
||||
<b-navbar-toggle target="nav_collapse"></b-navbar-toggle>
|
||||
|
||||
<b-navbar-brand href="#">PhotoPrism</b-navbar-brand>
|
||||
<b-navbar-brand href="/"><img src="/assets/img/logo.png" alt="PhotoPrism"></b-navbar-brand>
|
||||
|
||||
<b-collapse is-nav id="nav_collapse">
|
||||
|
||||
<b-navbar-nav>
|
||||
<b-nav-item href="#">Browse</b-nav-item>
|
||||
<b-nav-item href="#">Import</b-nav-item>
|
||||
<b-nav-item href="#">Export</b-nav-item>
|
||||
<b-nav-item to="/photos" class="nav-item-photos">Photos</b-nav-item>
|
||||
<b-nav-item to="/albums" class="nav-item-albums">Albums</b-nav-item>
|
||||
<b-nav-item to="/import" class="nav-item-import">Import</b-nav-item>
|
||||
<b-nav-item to="/export" class="nav-item-export">Export</b-nav-item>
|
||||
<b-nav-item to="/settings" class="nav-item-settings">Settings</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
|
||||
<!-- Right aligned nav items -->
|
||||
|
@ -22,21 +24,6 @@
|
|||
<b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button>
|
||||
</b-nav-form>
|
||||
|
||||
<b-nav-item-dropdown text="Lang" right>
|
||||
<b-dropdown-item href="#">EN</b-dropdown-item>
|
||||
<b-dropdown-item href="#">ES</b-dropdown-item>
|
||||
<b-dropdown-item href="#">RU</b-dropdown-item>
|
||||
<b-dropdown-item href="#">FA</b-dropdown-item>
|
||||
</b-nav-item-dropdown>
|
||||
|
||||
<b-nav-item-dropdown right>
|
||||
<!-- Using button-content slot -->
|
||||
<template slot="button-content">
|
||||
User
|
||||
</template>
|
||||
<b-dropdown-item href="#">Profile</b-dropdown-item>
|
||||
<b-dropdown-item href="#">Signout</b-dropdown-item>
|
||||
</b-nav-item-dropdown>
|
||||
</b-navbar-nav>
|
||||
|
||||
</b-collapse>
|
||||
|
|
|
@ -3917,6 +3917,10 @@ istanbul-lib-instrument@^1.4.2:
|
|||
istanbul-lib-coverage "^1.2.0"
|
||||
semver "^5.3.0"
|
||||
|
||||
jquery@^3.1.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
|
||||
|
||||
js-base64@^2.1.8, js-base64@^2.1.9:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033"
|
||||
|
@ -4021,6 +4025,18 @@ jsprim@^1.2.2:
|
|||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
justified-gallery@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/justified-gallery/-/justified-gallery-0.1.0.tgz#b4b861accd5641e47d223e649ea493bf05dc2794"
|
||||
dependencies:
|
||||
jquery "^3.1.0"
|
||||
|
||||
justified-layout@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/justified-layout/-/justified-layout-2.1.1.tgz#22da0c296d3a95b7a3d5fb7f48dbbe0e6539b7f1"
|
||||
dependencies:
|
||||
merge "1.2.0"
|
||||
|
||||
karma-chrome-launcher@^2.1.1:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
|
||||
|
@ -4427,6 +4443,10 @@ merge-descriptors@1.0.1:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
|
||||
merge@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
|
@ -7057,6 +7077,13 @@ vue-hot-reload-api@^2.0.11:
|
|||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
|
||||
|
||||
vue-justified-layout@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-justified-layout/-/vue-justified-layout-0.1.0.tgz#f26b606614719697aeff98f26b68795b926ae013"
|
||||
dependencies:
|
||||
justified-layout "^2.1.1"
|
||||
vue "^2.4.4"
|
||||
|
||||
vue-loader@^11.1.4:
|
||||
version "11.3.4"
|
||||
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-11.3.4.tgz#65e10a44ce092d906e14bbc72981dec99eb090d2"
|
||||
|
|
|
@ -34,7 +34,13 @@ func (i *Indexer) GetImageTags(jpeg *MediaFile) (result []Tag) {
|
|||
|
||||
for _, tag := range tags {
|
||||
if tag.Probability > 0.2 {
|
||||
result = append(result, Tag{Label: tag.Label})
|
||||
var tagModel Tag
|
||||
|
||||
if res := i.db.First(&tagModel, "label = ?", tag.Label); res.Error != nil {
|
||||
tagModel.Label = tag.Label
|
||||
}
|
||||
|
||||
result = append(result, tagModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
photo.go
4
photo.go
|
@ -6,9 +6,11 @@ import (
|
|||
|
||||
type Photo struct {
|
||||
gorm.Model
|
||||
Title string
|
||||
Description string `gorm:"type:text;"`
|
||||
CanonicalName string
|
||||
PerceptualHash string
|
||||
Tags []Tag `gorm:"many2many:photo_tags;"`
|
||||
Tags []Tag `gorm:"many2many:photo_tags;"`
|
||||
Files []File
|
||||
Albums []Album `gorm:"many2many:album_photos;"`
|
||||
Author string
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
server/assets/img/logo.png
Normal file
BIN
server/assets/img/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"github.com/photoprism/photoprism"
|
||||
)
|
||||
|
||||
func Start(address string, port int) {
|
||||
|
@ -14,11 +15,31 @@ func Start(address string, port int) {
|
|||
router.StaticFile("/favicon.ico", "./server/assets/favicon.ico")
|
||||
router.StaticFile("/robots.txt", "./server/assets/robots.txt")
|
||||
|
||||
// JSON-REST API Version 1
|
||||
v1 := router.Group("/v1")
|
||||
{
|
||||
v1.GET("/photos", func(c *gin.Context) {
|
||||
|
||||
photos := []*photoprism.Photo{ &photoprism.Photo{Title: "Bar"}, &photoprism.Photo{ Title: "Foo" } }
|
||||
|
||||
c.JSON(http.StatusOK, photos)
|
||||
})
|
||||
|
||||
v1.GET("/albums", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||
})
|
||||
|
||||
v1.GET("/tags", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||
})
|
||||
}
|
||||
|
||||
router.Static("/assets", "./server/assets")
|
||||
|
||||
router.NoRoute(func(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "index.tmpl", gin.H{
|
||||
"title": "PhotoPrism",
|
||||
"debug": true,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,20 +1,32 @@
|
|||
<!doctype html>
|
||||
<html class="no-js" lang="">
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title></title>
|
||||
<title>{{ .title }}</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
|
||||
<link rel="stylesheet" href="/assets/build/app.css">
|
||||
|
||||
<script>
|
||||
window.appConfig = {
|
||||
appName: "{{ .title }}",
|
||||
appVersion: "1.0.0",
|
||||
debug: {{ .debug }}
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!--[if lt IE 8]>
|
||||
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
||||
<![endif]-->
|
||||
|
||||
<div id="alerts"></div>
|
||||
|
||||
<div id="app" class="container">
|
||||
<div class="loading">
|
||||
<img src="/assets/img/ajax-loader.gif">
|
||||
|
|
2
tag.go
2
tag.go
|
@ -6,5 +6,5 @@ import (
|
|||
|
||||
type Tag struct {
|
||||
gorm.Model
|
||||
Label string
|
||||
Label string `gorm:"type:varchar(100);unique_index"`
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue