Skip to content

Commit

Permalink
Merge pull request #653 from photonia-io/photo-page-overhaul
Browse files Browse the repository at this point in the history
Photo page overhaul
  • Loading branch information
janosrusiczki authored Mar 11, 2024
2 parents 3c656ad + 3712c7a commit c51611d
Show file tree
Hide file tree
Showing 15 changed files with 406 additions and 78 deletions.
File renamed without changes.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ Or use [overmind](https://github.com/DarthSim/overmind): `overmind s -N -f Procf
-e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \
selenium/node-chrome:latest

## Deployment
## Versioning & Deployment

1. Draft a new release on the [releases page](https://github.com/photonia-io/photonia/releases)
1. Update the [changelog](CHANGELOG.md)
2. Draft a new release on the [releases page](https://github.com/photonia-io/photonia/releases)
- Create a tag with the prefix **release-** and the version, eg: **0.1.3** (resulting tag: **release-0.1.3**)
- Prefix the release title with the release version, eg: **0.1.3 - An awesome release**
2. Publish the release
3. Go to Jenkins and build the tag
3. Publish the release
4. Go to Jenkins and build the tag
6 changes: 6 additions & 0 deletions app/graphql/graphql_query_collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ class GraphqlQueryCollection
extralargeImageUrl: imageUrl(type: "extralarge")
takenAt
isTakenAtFromExif
exifExists
exifCameraFriendlyName
exifFNumber
exifExposureTime
exifFocalLength
exifIso
postedAt
impressionsCount
previousPhoto {
Expand Down
10 changes: 10 additions & 0 deletions app/graphql/types/photo_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ class PhotoType < Types::BaseObject

field :albums, [AlbumType], 'Albums the photo belongs to', null: true
field :description, String, 'Description', null: false
field :exif_camera_friendly_name, String, 'Camera friendly name', null: true
field :exif_f_number, Float, 'F number', null: true
field :exif_exposure_time, String, 'Exposure time', null: true
field :exif_iso, Integer, 'ISO', null: true
field :exif_exists, Boolean, 'Whether EXIF data exists', null: true
field :exif_focal_length, Float, 'Focal length', null: true
field :height, Integer, 'Height of the photo in pixels', null: true
field :id, String, 'ID of the photo', null: false
field :impressions_count, Integer, 'Number of impressions', null: true
Expand Down Expand Up @@ -89,5 +95,9 @@ def width
def height
@object.pixel_height
end

def exif_exists
@object.exif_exists?
end
end
end
7 changes: 7 additions & 0 deletions app/javascript/entrypoints/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ document.addEventListener("DOMContentLoaded", () => {
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ top: 0, behavior: "smooth" });
}, 50);
});
},
});

const tokenStore = useTokenStore(pinia);
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/photos/display-hero.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ const showLabels = computed(() => {
display: flex;
flex-direction: column;
border-radius: 5px;
overflow: scroll;
overflow: auto;
max-height: calc(100% - 15px);
}
Expand Down
28 changes: 15 additions & 13 deletions app/javascript/photos/photo-info.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<template>
<SidebarHeader icon="fas fa-info-circle" title="Info" />
<div class="block">
<span class="icon-text is-size-7">
<!-- display views -->
<PhotoInfobox>
<template #header>
<SidebarHeader icon="fas fa-info-circle" title="Info" />
</template>
<div class="icon-text">
<span class="icon"><i class="fas fa-eye"></i></span>
<span class="has-text-weight-semibold">Views:</span>
<span v-if="!loading" class="ml-1">{{ photo.impressionsCount }}</span>
</span>
<span class="icon-text is-size-7">
</div>
<div class="icon-text">
<span class="icon"><i class="fas fa-camera"></i></span>
<span class="has-text-weight-semibold">Date Taken:</span>
<span v-if="!loading" class="ml-1">{{
Expand All @@ -19,28 +20,29 @@
>
EXIF
</span>
</span>
<span class="icon-text is-size-7">
</div>
<div class="icon-text">
<span class="icon"><i class="fas fa-arrow-circle-up"></i></span>
<span class="has-text-weight-semibold">Date Posted:</span>
<span v-if="!loading" class="ml-1">{{
momentFormat(photo.postedAt)
}}</span>
</span>
<span
</div>
<div
v-if="!loading && photo.rekognitionLabelModelVersion !== ''"
class="icon-text is-size-7"
class="icon-text"
>
<span class="icon"><i class="fas fa-robot"></i></span>
<span class="has-text-weight-semibold"
>Rekognition Label Model Version:</span
>
<span class="ml-1">{{ photo.rekognitionLabelModelVersion }}</span>
</span>
</div>
</div>
</PhotoInfobox>
</template>

<script setup>
import PhotoInfobox from "./photo-infobox.vue";
import SidebarHeader from "./sidebar-header.vue";
import moment from "moment/min/moment-with-locales";
Expand Down
34 changes: 34 additions & 0 deletions app/javascript/photos/photo-infobox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<div class="message is-smallish is-lightgray">
<div class="message-header">
<slot name="header"></slot>
</div>
<div class="message-body">
<slot></slot>
</div>
</div>
</template>

<style scoped>
.message {
background-color: hsl(0, 0%, 98%);
}
.message p {
display: block;
}
.message.is-smallish {
font-size: 0.9rem;
}
.message-body {
padding: 1em 1em;
}
.message.is-lightgray .message-header {
background-color: hsl(0, 0%, 95%);
color: #363636;
}
.message.is-lightgray .message-body {
color: #363636;
}
</style>
134 changes: 83 additions & 51 deletions app/javascript/photos/show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,45 +59,89 @@
@delete-photo="deletePhoto"
/>

<PhotoInfo :photo="photo" :loading="loading" />

<div
class="message is-smallish is-lightgray"
v-if="photo.labels?.length > 0"
>
<div class="message-header">Labels</div>
<div class="message-body">
<div class="tags">
<LabelListItem
v-for="label in photo.labels"
@highlight-label="highlightLabel"
@un-highlight-label="unHighlightLabel"
:label="label"
:hoverable="false"
:key="label.id"
/>
</div>
<label class="checkbox">
<input type="checkbox" v-model="showLabelsOnHero" />
Display labels on the photo
</label>
<div class="columns equal-height-columns">
<div class="column is-half">
<PhotoInfo :photo="photo" :loading="loading" />
</div>
<div class="column is-half">
<PhotoInfobox>
<template #header>
<SidebarHeader icon="fas fa-camera" title="EXIF" />
</template>
<div class="icon-text">
<span class="icon"
><i class="fas fa-camera-retro"></i
></span>
<span v-if="!loading">
<span v-if="photo.exifExists">
{{ photo.exifCameraFriendlyName }}
</span>
<span v-else>
<em>No EXIF data available</em>
</span>
</span>
</div>
<div class="icon-text">
<span class="icon"><i class="fas fa-cog"></i></span>
<span v-if="!loading">
<span v-if="photo.exifExists">
f/{{ photo.exifFNumber }} &middot;
{{ photo.exifExposureTime }}s &middot;
{{ photo.exifFocalLength }}mm &middot; ISO
{{ photo.exifIso }}
</span>
<span v-else>
<em>No EXIF data available</em>
</span>
</span>
</div>
</PhotoInfobox>
</div>
</div>

<SidebarHeader icon="fas fa-tag" title="Tags" />
<div class="tags">
<Tag v-for="tag in photo.userTags" :key="tag.id" :tag="tag" />
</div>

<SidebarHeader icon="fas fa-robot" title="Machine Tags" />
<div class="tags">
<Tag
v-for="tag in photo.machineTags"
:key="tag.id"
:tag="tag"
type="machine"
/>
</div>
<PhotoInfobox v-if="photo.labels?.length > 0">
<template #header>Labels</template>
<div class="tags">
<LabelListItem
v-for="label in photo.labels"
@highlight-label="highlightLabel"
@un-highlight-label="unHighlightLabel"
:label="label"
:hoverable="false"
:key="label.id"
/>
</div>
<label class="checkbox">
<input type="checkbox" v-model="showLabelsOnHero" />
Display labels on the photo
</label>
</PhotoInfobox>

<PhotoInfobox>
<template #header
><SidebarHeader icon="fas fa-tag" title="Tags"
/></template>
<div class="tags" v-if="photo.userTags?.length > 0">
<Tag v-for="tag in photo.userTags" :key="tag.id" :tag="tag" />
</div>
<span v-else>
<em>There are no user tags for this photo.</em>
</span>
</PhotoInfobox>

<PhotoInfobox>
<template #header>
<SidebarHeader icon="fas fa-robot" title="Machine Tags" />
</template>
<div class="tags">
<Tag
v-for="tag in photo.machineTags"
:key="tag.id"
:tag="tag"
type="machine"
/>
</div>
</PhotoInfobox>
</div>
<!-- End left column -->
<div class="column is-one-quarter">
Expand Down Expand Up @@ -227,6 +271,7 @@ import PhotoTitleEditable from "./photo-title-editable.vue";
import PhotoDescriptionEditable from "./photo-description-editable.vue";
import PhotoAdministration from "./photo-administration.vue";
import PhotoInfo from "./photo-info.vue";
import PhotoInfobox from "./photo-infobox.vue";
import SmallNavigationButton from "@/photos/small-navigation-button.vue";
import DisplayHero from "./display-hero.vue";
import SidebarHeader from "./sidebar-header.vue";
Expand Down Expand Up @@ -407,24 +452,11 @@ const navigateToPreviousPhoto = () => {
</script>
<style scoped>
.message.is-smallish {
font-size: 0.84rem;
}
.message-body {
padding: 1em 1em;
}
.message-body .tags {
margin-bottom: 0.2em;
}
.message.is-lightgray .message-header {
background-color: #dedede;
color: #363636;
}
.message.is-lightgray .message-body {
background-color: #f0f0f4;
color: #363636;
.equal-height-columns .message {
height: 100%;
}
</style>
10 changes: 4 additions & 6 deletions app/javascript/photos/sidebar-header.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<template>
<h3 class="mb-2">
<span class="icon-text">
<span class="icon"><i :class="icon"></i></span>
<span>{{ title }}</span>
</span>
</h3>
<span class="icon-text">
<span class="icon"><i :class="icon"></i></span>
<span>{{ title }}</span>
</span>
</template>

<script setup>
Expand Down
47 changes: 47 additions & 0 deletions app/models/concerns/exif_utilities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module EXIFUtilities
extend ActiveSupport::Concern

def exif_ifd0
exif['ifd0']
end

def exif_ifd1
exif['ifd1']
end

def exif_exif
exif['exif']
end

def exif_camera_make
exif_ifd0['make']
end

def exif_camera_model
exif_ifd0['model']
end

def exif_camera_friendly_name
if exif_exists? && exif_camera_make && exif_camera_model
CameraUtilities.new(exif_camera_make, exif_camera_model).friendly_name
else
''
end
end

def exif_f_number
exif_exif['fnumber'].to_f if exif_exists? && exif_exif['fnumber']
end

def exif_exposure_time
exif_exif['exposure_time'] if exif_exists? && exif_exif['exposure_time']
end

def exif_focal_length
exif_exif['focal_length'].to_f if exif_exists? && exif_exif['focal_length']
end

def exif_iso
exif_exif['iso_speed_ratings'].to_i if exif_exists? && exif_exif['iso_speed_ratings']
end
end
1 change: 1 addition & 0 deletions app/models/photo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Photo < ApplicationRecord

include ImageUploader::Attachment(:image)
include SerialNumberSetter
include EXIFUtilities

include PgSearch::Model
pg_search_scope :search,
Expand Down
Loading

0 comments on commit c51611d

Please sign in to comment.