Skip to content

Commit

Permalink
Merge pull request #3174 from manuelmeister/improve/picasso
Browse files Browse the repository at this point in the history
Improve picasso & avatars
  • Loading branch information
pmattmann authored Jan 24, 2023
2 parents 2cdafbb + 55a687c commit 7dadcf0
Show file tree
Hide file tree
Showing 28 changed files with 1,018 additions and 369 deletions.
65 changes: 65 additions & 0 deletions common/helpers/__tests__/interpolation.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { lerp, clamp, invlerp, range } from '../interpolation.js'

describe('lerp', () => {
it.each([
[[0, 50, 0.5], 25],
[[1, 3, 0.5], 2],
[[0, 5, 0.2], 1],
[[2, 7, 1], 7],
[[8, 4, 0.5], 6],
[[5, 4, 1], 4],
[[3, 7, 2], 11],
[[2, 3, 3], 5],
[[-8, -4, 0.5], -6],
[[-2, -4, 0.25], -2.5],
[[0, 10, 0.1], 1],
[[10, 50, 1], 50],
])('maps %p to %p', (input, expected) => {
expect(lerp(...input)).toEqual(expected)
})
})

describe('clamp', () => {
it.each([
[[0.5, 0, 50], 0.5],
[[3, 0, 5], 3],
[[2, -5, 10], 2],
[[8, 1, 3], 3],
[[5, -1, 2], 2],
[[3, 5, 10], 5],
[[1, 2, 3], 2],
[[11, 0, 10], 10],
[[1, 10, 50], 10],
])('maps %p to %p', (input, expected) => {
expect(clamp(...input)).toEqual(expected)
})
})

describe('invlerp', () => {
it.each([
[[0, 2, 1], 0.5],
[[-10, 0, -5], 0.5],
[[-10, 10, 8], 0.9],
[[3, 7, 5], 0.5],
[[-1, 1, 10], 1],
[[99, 101, 42], 0],
[[-100, 100, -100], 0],
])('maps %p to %p', (input, expected) => {
expect(invlerp(...input)).toEqual(expected)
})
})

describe('range', () => {
it.each([
[[0, 1, 10, 20, 0.5], 15],
[[10, 0, 20, 40, 7.5], 25],
[[-10, 10, 8, 96, 5], 74],
[[16, 32, 8, 14, 24], 11],
[[-100, 100, 0, 100, 0], 50],
[[-100, 100, 0, 100, 50], 75],
[[42, 42, 0, 100, 42], NaN],
[[1337, 50, 0, 100, 42], 100],
])('maps %p to %p', (input, expected) => {
expect(range(...input)).toEqual(expected)
})
})
39 changes: 39 additions & 0 deletions common/helpers/interpolation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Curve fitting
* @param x
* @param y
* @param a
* @returns {number}
*/
export const lerp = (x, y, a) => x * (1 - a) + y * a

/**
* Clamps value between min and max
* @param a
* @param min
* @param max
* @returns {number}
*/
export const clamp = (a, min = 0, max = 1) => Math.min(max, Math.max(min, a))

/**
* Inverse curve fitting function
* @param x
* @param y
* @param a
* @returns {number}
*/
export const invlerp = (x, y, a) => clamp((a - x) / (y - x))

/**
* Maps input to output range
* @param inputStart
* @param inputEnd
* @param outputStart
* @param outputEnd
* @param input
* @returns number
*/
export function range(inputStart, inputEnd, outputStart, outputEnd, input) {
return lerp(outputStart, outputEnd, invlerp(inputStart, inputEnd, input))
}
2 changes: 1 addition & 1 deletion frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</v-main>

<!-- footer -->
<v-footer v-if="$vuetify.breakpoint.smAndUp" app color="grey lighten-5">
<v-footer v-if="$vuetify.breakpoint.mdAndUp" app color="grey lighten-5">
<small
>eCamp
<a v-if="version" :href="versionLink" target="_blank">
Expand Down
28 changes: 27 additions & 1 deletion frontend/src/components/activity/ActivityResponsibles.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,30 @@
small-chips
v-bind="$attrs"
@input="onInput"
/>
>
<template #selection="{ item }">
<v-chip :key="item.value" small class="mx-0">
<UserAvatar
:camp-collaboration="item.campCollaboration"
left
size="20"
class="ml-n3"
/>
<span>{{ item.text }}</span>
</v-chip>
</template>
</e-select>
</template>

<script>
import { serverErrorToString } from '@/helpers/serverError.js'
import campCollaborationDisplayName from '@/common/helpers/campCollaborationDisplayName.js'
import { isEqual, sortBy } from 'lodash'
import UserAvatar from '@/components/user/UserAvatar.vue'
export default {
name: 'ActivityResponsibles',
components: { UserAvatar },
props: {
activity: {
type: Object,
Expand Down Expand Up @@ -57,6 +71,7 @@ export default {
// following structure is defined by vuetify v-select items property
return {
value: value._meta.self,
campCollaboration: value,
text: campCollaborationDisplayName(value, this.$tc.bind(this)),
}
})
Expand Down Expand Up @@ -159,3 +174,14 @@ export default {
},
}
</script>
<style scoped lang="scss">
::v-deep(.v-select__selections) {
gap: 4px;
padding-top: 8px !important;
& input {
padding: 0;
}
}
</style>
9 changes: 4 additions & 5 deletions frontend/src/components/dashboard/ActivityRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@
<td style="width: 100%" class="contentrow">
<router-link
:to="routerLink"
class="text-decoration-none text-decoration-hover-underline black--text"
class="text-decoration-none text-decoration-hover-underline black--text font-weight-medium d-block"
>
{{ title }}<br />
</router-link>
<span class="e-subtitle">{{ location }}</span>
</td>
<td class="contentrow avatarrow overflow-visible">
<AvatarRow :camp-collaborations="collaborators" size="28" class="ml-auto" />
<AvatarRow :camp-collaborations="collaborators" max-size="28" class="ml-auto" />
</td>
</tr>
</template>

<script>
import AvatarRow from './AvatarRow.vue'
import AvatarRow from '@/components/generic/AvatarRow.vue'
import CategoryChip from '@/components/generic/CategoryChip.vue'
import { dateHelperUTCFormatted } from '@/mixins/dateHelperUTCFormatted.js'
import TextAlignBaseline from '@/components/layout/TextAlignBaseline.vue'
Expand Down Expand Up @@ -97,10 +97,9 @@ tr + tr :is(td, th) {
}
.contentrow {
max-width: 100px;
max-width: 64px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.avatarrow {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<template>
<div class="avatarrow" :style="avatarrow">
<div class="e-avatarrow" :class="{ 'e-avatarrow--narrow': narrow }" :style="styles">
<div
v-for="campCollaboration in campCollaborations"
:key="campCollaboration && campCollaboration._meta.self"
class="avataritem"
class="e-avataritem"
>
<UserAvatar :size="Number(size)" :camp-collaboration="campCollaboration" />
<UserAvatar :size="size" :camp-collaboration="campCollaboration" />
</div>
</div>
</template>
Expand All @@ -18,46 +18,59 @@ export default {
components: { UserAvatar },
props: {
campCollaborations: { type: Array, default: () => [] },
size: { type: [Number, String], default: 20 },
maxSize: { type: [Number, String], default: 20 },
},
data: () => ({
maxHeight: 1000,
}),
computed: {
size() {
return Math.min(Number(this.maxSize), this.maxHeight)
},
maxWidth() {
return (
(this.campCollaborations?.length - 1) * (Number(this.size) * 0.25) +
Number(this.size)
)
return this.campCollaborations?.length * (this.size * 0.5) + this.size
},
narrow() {
return this.campCollaborations?.length > 3
},
avatarrow() {
styles() {
return {
'max-width': `${this.maxWidth}px`,
'font-size': `${this.size}px`,
}
},
},
mounted() {
this.maxHeight = this.$el.getBoundingClientRect().height
},
}
</script>
<style scoped lang="scss">
.avatarrow {
.e-avatarrow {
display: flex;
flex-direction: row-reverse;
gap: 0.75em;
gap: 0.8em;
@media #{map-get($display-breakpoints, 'md-and-up')} {
gap: 1.1em;
}
padding-left: 0.5em;
padding-right: 0.5em;
transition: gap 0.25s ease;
}
@media #{map-get($display-breakpoints, 'md-and-up')} {
.avatarrow {
gap: 1.1em;
.e-avatarrow--narrow {
@media #{map-get($display-breakpoints, 'md-and-up')} {
gap: 0.8em;
}
}
.avatarrow:hover {
.e-avatarrow:hover {
gap: 1.1em;
}
.avataritem {
.e-avataritem {
display: grid;
width: 0;
place-content: center;
Expand Down
41 changes: 40 additions & 1 deletion frontend/src/components/generic/LockIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
<v-icon v-if="value" small v-on="{ dblclick: iconDblClick, ...on }">
mdi-lock-open-variant
</v-icon>
<v-icon v-else small color="grey" v-on="{ dblclick: iconDblClick, ...on }">
<v-icon
v-else
small
color="grey"
:title="$tc('components.generic.lockIcon.doubleClickToUnlock')"
:class="{ 'e-shake-lock': shake }"
v-on="{ dblclick: iconDblClick, ...on }"
>
mdi-lock
</v-icon>
</template>
Expand All @@ -30,6 +37,10 @@ export default {
required: false,
default: false,
},
shake: {
type: Boolean,
default: false,
},
},
methods: {
iconDblClick() {
Expand All @@ -43,4 +54,32 @@ export default {
.v-icon {
cursor: pointer;
}
.e-shake-lock {
animation: horizontal-shaking 0.5s linear 1;
}
@keyframes horizontal-shaking {
0% {
transform: translateX(0);
}
10% {
transform: translateX(5px);
}
25% {
transform: translateX(-5px);
}
45% {
transform: translateX(4px);
}
65% {
transform: translateX(-4px);
}
80% {
transform: translateX(3px);
}
100% {
transform: translateX(0);
}
}
</style>
6 changes: 3 additions & 3 deletions frontend/src/components/program/ScheduleEntries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

<v-btn
v-if="showButton"
:fixed="$vuetify.breakpoint.xs"
:absolute="!$vuetify.breakpoint.xs"
:fixed="$vuetify.breakpoint.mdAndUp"
:absolute="!$vuetify.breakpoint.mdAndUp"
dark
fab
style="z-index: 3"
Expand Down Expand Up @@ -103,7 +103,7 @@ export default {
.fab--bottom_nav {
position: fixed;
bottom: calc(16px + 56px + env(safe-area-inset-bottom)) !important;
@media #{map-get($display-breakpoints, 'sm-and-up')} {
@media #{map-get($display-breakpoints, 'md-and-up')} {
bottom: calc(16px + 36px + env(safe-area-inset-bottom)) !important;
}
}
Expand Down
Loading

0 comments on commit 7dadcf0

Please sign in to comment.