Add support for profile photos; default image
This commit is contained in:
@@ -3,6 +3,7 @@ import NavBarComponent from './dash/NavBar.component.js'
|
||||
import MessageContainerComponent from './dash/message/MessageContainer.component.js'
|
||||
import EditProfileComponent from './dash/profile/EditProfile.component.js'
|
||||
import AppPasswordFormComponent from './dash/profile/form/AppPassword.component.js'
|
||||
import ProfilePhotoUploaderComponent from './dash/profile/form/ProfilePhotoUploader.component.js'
|
||||
|
||||
import ListingComponent from './cobalt/Listing.component.js'
|
||||
import FormComponent from './cobalt/Form.component.js'
|
||||
@@ -13,6 +14,7 @@ const dash_components = {
|
||||
MessageContainerComponent,
|
||||
EditProfileComponent,
|
||||
AppPasswordFormComponent,
|
||||
ProfilePhotoUploaderComponent,
|
||||
|
||||
ListingComponent,
|
||||
FormComponent,
|
||||
|
||||
@@ -13,7 +13,10 @@ const template = `
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-8 offset-2 col-sm-4 offset-sm-0">
|
||||
<img src="/assets/profile.jpg" alt="Profile Image" class="img-fluid">
|
||||
<img src="/api/v1/profile/me/photo" alt="Profile Image" ref="photo" class="img-fluid">
|
||||
<div class="overlay">
|
||||
<button class="btn btn-outline-light" @click="on_profile_change_click">Change</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8 offset-sm-0 col-12 text-sm-left text-center pad-top">
|
||||
<div class="card-title"><h3>{{ profile_first }} {{ profile_last }}</h3></div>
|
||||
@@ -140,6 +143,11 @@ const template = `
|
||||
ref="app_password_modal"
|
||||
@modal-success="load_app_passwords"
|
||||
></coreid-form-app-password>
|
||||
<coreid-profile-photo-uploader
|
||||
ref="profile_photo_uploader"
|
||||
:user-id="user_id"
|
||||
@upload="on_profile_photo_upload"
|
||||
></coreid-profile-photo-uploader>
|
||||
</div>
|
||||
`
|
||||
|
||||
@@ -187,6 +195,17 @@ export default class EditProfileComponent extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
on_profile_change_click() {
|
||||
this.$refs.profile_photo_uploader.show()
|
||||
}
|
||||
|
||||
async on_profile_photo_upload() {
|
||||
this.$refs.profile_photo_uploader.close()
|
||||
let src = this.$refs.photo.src
|
||||
if ( src.indexOf('?') > 0 ) src = src.split('?')[0]
|
||||
this.$refs.photo.src = `${src}?i=${(new Date).getTime()}`
|
||||
}
|
||||
|
||||
valid_email() {
|
||||
return this.$refs.email_input.validity.valid
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Component } from '../../../../lib/vues6/vues6.js'
|
||||
|
||||
const template = `
|
||||
<div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" ref="modal">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content" v-if="ready">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Change Profile Photo</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="file" name="image" ref="input" required>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="do_upload"
|
||||
>Change</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
export default class ProfilePhotoUploaderComponent extends Component {
|
||||
static get selector() { return 'coreid-profile-photo-uploader' }
|
||||
static get template() { return template }
|
||||
static get params() { return [] }
|
||||
|
||||
ready = false
|
||||
|
||||
show() {
|
||||
this.ready = true
|
||||
this.$nextTick(() => {
|
||||
$(this.$refs.modal).modal()
|
||||
})
|
||||
}
|
||||
|
||||
close() {
|
||||
$(this.$refs.modal).modal('hide')
|
||||
}
|
||||
|
||||
async do_upload() {
|
||||
if ( this.$refs.input.files.length < 1 ) return
|
||||
const data = new FormData()
|
||||
data.append('photo', this.$refs.input.files[0])
|
||||
try {
|
||||
await axios.post(`/api/v1/profile/me/photo`, data, { // TODO support passed-in user_id
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
}
|
||||
})
|
||||
this.$emit('upload')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
app/assets/humans.txt
Normal file
1
app/assets/humans.txt
Normal file
@@ -0,0 +1 @@
|
||||
Stock profile photo thanks to: https://www.flaticon.com/authors/vitaly-gorbachev
|
||||
@@ -61,3 +61,24 @@ body {
|
||||
.pad-top {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(20, 20, 20, 0.4);
|
||||
opacity: 0;
|
||||
|
||||
transition: all 0.1s linear;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
app/assets/people.png
Normal file
BIN
app/assets/people.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB |
Reference in New Issue
Block a user