Switch from yarn to npm and other frontend improvements, see #3

See https://iamturns.com/yarn-vs-npm-2018/
This commit is contained in:
Michael Mayer 2019-05-07 02:05:01 +02:00
parent 55c19635c9
commit 53a5d84653
18 changed files with 11265 additions and 8521 deletions

View file

@ -1,4 +1,4 @@
FROM photoprism/development:20190503
FROM photoprism/development:20190506
# Set up project directory
WORKDIR "/go/src/github.com/photoprism/photoprism"

View file

@ -22,7 +22,7 @@ install-config:
build:
scripts/build.sh debug $(BINARY_NAME)
js:
(cd frontend && yarn install --frozen-lockfile --prod)
(cd frontend && npm install --production)
(cd frontend && env NODE_ENV=production npm run build)
start:
go run cmd/photoprism/photoprism.go start

View file

@ -55,15 +55,12 @@ ENV TF_CPP_MIN_LOG_LEVEL 2
# Install NPM (NodeJS)
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install nodejs
# Install YARN (Package Manager)
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && \
apt-get install yarn && \
apt-get install nodejs && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN npm install -g npm
RUN npm config set cache ~/.cache/npm
# Install Go
ENV GOLANG_VERSION 1.12.4

View file

@ -1,4 +1,4 @@
FROM photoprism/development:20190503 as build
FROM photoprism/development:20190506 as build
# Set up project directory
WORKDIR "/go/src/github.com/photoprism/photoprism"

View file

@ -1,4 +1,4 @@
FROM photoprism/development:20190503
FROM photoprism/development:20190506
# Install Python and TensorFlow
RUN apt-get update && apt-get install -y --no-install-recommends \

View file

@ -1,5 +1,6 @@
@import url("../node_modules/material-design-icons-iconfont/dist/material-design-icons.css");
@import url("../node_modules/vuetify/dist/vuetify.min.css");
@import url("../node_modules/leaflet/dist/leaflet.css");
@import url("photo.css");
@ -41,4 +42,4 @@ main {
width: 19px;
right: -20px;
top: -8px;
}
}

10987
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"name": "photoprism",
"version": "1.0.0",
"description": "Web application frontend for PhotoPrism",
"description": "Single-page Web app frontend for PhotoPrism",
"author": "Michael Mayer",
"private": true,
"scripts": {
@ -12,6 +12,7 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.2.0",
"@types/leaflet": "^1.4.4",
"autoprefixer": "^6.7.2",
"axios": "^0.16.1",
"axios-mock-adapter": "^1.8.1",
@ -55,6 +56,7 @@
"karma-phantomjs-launcher": "^1.0.4",
"karma-webdriver-launcher": "^1.0.5",
"karma-webpack": "^2.0.3",
"leaflet": "^1.4.0",
"material-design-icons-iconfont": "^3.0.3",
"mocha": "^3.3.0",
"node-sass": "^4.9.2",
@ -78,6 +80,7 @@
"vue-style-loader": "^2.0.0",
"vue-template-compiler": "^2.4.4",
"vue-truncate-filter": "^1.1.7",
"vue2-leaflet": "^2.1.1",
"vuelidate": "^0.4.3",
"vuetify": "^1.2.3",
"webpack": "^3.12.0",

View file

@ -6,7 +6,7 @@ import App from 'app/main.vue';
import routes from 'app/routes';
import Api from 'common/api';
import Config from 'common/config';
import AppComponents from 'component/app-components';
import Components from 'component/components';
import Alert from 'common/alert';
import Session from 'common/session';
import Event from 'pubsub-js';
@ -15,15 +15,18 @@ import InfiniteScroll from 'vue-infinite-scroll';
import VueTruncate from 'vue-truncate-filter';
import VueFullscreen from 'vue-fullscreen';
// Initialize client-side session
const session = new Session(window.localStorage);
const config = new Config(window.localStorage, window.appConfig);
// Set global helpers
Vue.prototype.$event = Event;
Vue.prototype.$alert = Alert;
Vue.prototype.$session = session;
Vue.prototype.$api = Api;
Vue.prototype.$config = config;
// Register Vuetify
Vue.use(Vuetify, {
theme: {
primary: '#FFD600',
@ -38,22 +41,25 @@ Vue.use(Vuetify, {
},
});
// Register other VueJS plugins
Vue.use(Moment);
Vue.use(InfiniteScroll);
Vue.use(VueTruncate);
Vue.use(VueFullscreen);
Vue.use(AppComponents);
Vue.use(Components);
Vue.use(Router);
// Configure client-side routing
const router = new Router({
routes,
mode: 'history',
saveScrollPosition: true,
});
// Run app
/* eslint-disable no-unused-vars */
const app = new Vue({
el: '#app',
router,
render: h => h(App),
});
});

View file

@ -0,0 +1,110 @@
<template>
<div>
<v-toolbar flat color="blue-grey lighten-4">
<v-toolbar-title>Calendar</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-container>
<v-layout wrap>
<v-flex
xs12
class="mb-3"
>
<v-sheet height="500">
<v-calendar
ref="calendar"
v-model="start"
:type="type"
:end="end"
color="primary"
></v-calendar>
</v-sheet>
</v-flex>
<v-flex
sm4
xs12
class="text-sm-left text-xs-center"
>
<v-btn @click="$refs.calendar.prev()">
<v-icon
dark
left
>
keyboard_arrow_left
</v-icon>
Prev
</v-btn>
</v-flex>
<v-flex
sm4
xs12
class="text-xs-center"
>
<v-select
v-model="type"
:items="typeOptions"
label="Type"
></v-select>
</v-flex>
<v-flex
sm4
xs12
class="text-sm-right text-xs-center"
>
<v-btn @click="$refs.calendar.next()">
Next
<v-icon
right
dark
>
keyboard_arrow_right
</v-icon>
</v-btn>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
export default {
name: 'calendar',
data: () => ({
type: 'month',
start: '2019-01-01',
end: '2019-01-06',
typeOptions: [
{text: 'Day', value: 'day'},
{text: '4 Day', value: '4day'},
{text: 'Week', value: 'week'},
{text: 'Month', value: 'month'},
{text: 'Custom Daily', value: 'custom-daily'},
{text: 'Custom Weekly', value: 'custom-weekly'}
]
}),
methods: {}
};
</script>
<style scoped>
a {
color: #00B8D4;
}
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
</style>

View file

@ -1,25 +1,38 @@
<template>
<v-container fluid>
<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>
</v-container>
<div>
<v-toolbar flat color="blue-grey lighten-4">
<v-toolbar-title>Export</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-container>
<p>
Issues labeled <a href="https://github.com/photoprism/photoprism/labels/help%20wanted">help wanted</a> /
<a href="https://github.com/photoprism/photoprism/labels/easy">easy</a> can be good (first)
contributions.
Our <a href="https://github.com/photoprism/photoprism/wiki">Developer Guide</a> contains all information
necessary to get you started.
</p>
</v-container>
</div>
</template>
<script>
export default {
name: 'browse',
name: 'todo',
data() {
return {
};
return {};
},
methods: {
}
methods: {}
};
</script>
<style scoped>
a {
color: #00B8D4;
}
h1, h2 {
font-weight: normal;
}

View file

@ -0,0 +1,45 @@
<template>
<v-container fluid fill-height class="pa-0 map">
<l-map :zoom="zoom" :center="center">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="marker"></l-marker>
</l-map>
</v-container>
</template>
<script>
export default {
name: 'places',
data() {
return {
zoom: 13,
center: L.latLng(47.413220, -1.219482),
url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
marker: L.latLng(47.413220, -1.219482),
}
},
methods: {},
};
</script>
<style scoped>
.map {
width: 100%;
height: 100%;
}
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
</style>

View file

@ -1,22 +1,27 @@
<template>
<v-container fluid>
<h1 class="md-display-1">Settings</h1>
<p class="md-subheading">
<div>
<v-toolbar flat color="blue-grey lighten-4">
<v-toolbar-title>Settings</v-toolbar-title>
</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>
</v-container>
<v-spacer></v-spacer>
</v-toolbar>
<v-container>
<p>
<v-btn v-on:click="showSuccess()">Show Success</v-btn>
<v-btn v-on:click="showInfo()">Show Info</v-btn>
<v-btn v-on:click="showError()">Show Error</v-btn>
<v-btn v-on:click="showWarning()">Show Warning</v-btn>
</p>
</v-container>
</div>
</template>
<script>
export default {
name: 'dashboard',
name: 'settings',
data() {
return {
};
return {};
},
methods: {
showSuccess() {
@ -36,6 +41,10 @@
</script>
<style scoped>
a {
color: #00B8D4;
}
h1, h2 {
font-weight: normal;
}

View file

@ -1,25 +1,38 @@
<template>
<v-container fluid>
<h1>TODO</h1>
<p class="md-subheading">
This page is not implemented yet
</p>
</v-container>
<div>
<v-toolbar flat color="blue-grey lighten-4">
<v-toolbar-title>Not implemented yet</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-container>
<p>
Issues labeled <a href="https://github.com/photoprism/photoprism/labels/help%20wanted">help wanted</a> /
<a href="https://github.com/photoprism/photoprism/labels/easy">easy</a> can be good (first)
contributions.
Our <a href="https://github.com/photoprism/photoprism/wiki">Developer Guide</a> contains all information
necessary to get you started.
</p>
</v-container>
</div>
</template>
<script>
export default {
name: 'todo',
data() {
return {
};
return {};
},
methods: {
}
methods: {}
};
</script>
<style scoped>
a {
color: #00B8D4;
}
h1, h2 {
font-weight: normal;
}

View file

@ -9,17 +9,19 @@ import Export from 'app/pages/export.vue';
import Settings from 'app/pages/settings.vue';
import Tags from 'app/pages/tags.vue';
import Todo from 'app/pages/todo.vue';
import Places from 'app/pages/places.vue';
import Calendar from 'app/pages/calendar.vue';
export default [
{ name: 'Home', path: '/', redirect: '/photos' },
{ name: 'Photos', path: '/photos', component: Photos },
{ name: 'PhotosEdit', path: '/photosEdit', component: PhotosEdit },
{ name: 'Filters', path: '/filters', component: Todo },
{ name: 'Calendar', path: '/calendar', component: Todo },
{ name: 'Calendar', path: '/calendar', component: Calendar },
{ name: 'Tags', path: '/tags', component: Tags },
{ name: 'Bookmarks', path: '/bookmarks', component: Todo },
{ name: 'Favorites', path: '/favorites', component: Todo },
{ name: 'Places', path: '/places', component: Todo },
{ name: 'Places', path: '/places', component: Places },
{ name: 'Albums', path: '/albums', component: Albums },
{ name: 'Albums2', path: '/albums2', component: Albums2 },
{ name: 'Import', path: '/import', component: Import },

View file

@ -1,15 +0,0 @@
import AppAlert from './app-alert.vue';
import AppNavigation from './app-navigation.vue';
import AppLoadingBar from './app-loading-bar.vue';
import PhotoSwipe from './photoswipe.vue';
const components = {};
components.install = (Vue) => {
Vue.component('app-alert', AppAlert);
Vue.component('photoswipe', PhotoSwipe);
Vue.component('app-navigation', AppNavigation);
Vue.component('app-loading-bar', AppLoadingBar);
};
export default components;

View file

@ -0,0 +1,29 @@
import AppAlert from './app-alert.vue';
import AppNavigation from './app-navigation.vue';
import AppLoadingBar from './app-loading-bar.vue';
import PhotoSwipe from './photoswipe.vue';
import {LMap, LMarker, LTileLayer} from 'vue2-leaflet';
import {Icon} from 'leaflet';
const components = {};
components.install = (Vue) => {
Vue.component('app-alert', AppAlert);
Vue.component('photoswipe', PhotoSwipe);
Vue.component('app-navigation', AppNavigation);
Vue.component('app-loading-bar', AppLoadingBar);
Vue.component('l-map', LMap);
Vue.component('l-tile-layer', LTileLayer);
Vue.component('l-marker', LMarker);
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
};
export default components;

File diff suppressed because it is too large Load diff