website/web/templates/partials/like_modal.html

209 lines
7.5 KiB
HTML
Raw Permalink Normal View History

2023-09-14 04:28:38 +00:00
<!-- "Likes" modal to see who liked a thing -->
<!-- Reusable "Liked by Alice, Bob and 5 others" widget that invokes
the Like Modal. Requirements: pass in a context providing the
following variables:
- LikeExample: slice of users
- LikeRemainder: integer
- LikeTableName: like 'photos'
- LikeTableID: integer
Call this like: {{template "like-example" .}}
-->
{{define "like-example"}}
{{$Outer := .}}
{{if .LikeExample}}
<div class="mt-4 mb-2 has-text-centered">
Liked by
<!-- User list -->
{{range $i, $User := .LikeExample}}
<!-- Avatar -->
<figure class="image is-16x16 is-inline-block">
<a href="/u/{{$User.Username}}" class="has-text-dark">
{{if $User.ProfilePhoto.ID}}
{{if and (eq $User.ProfilePhoto.Visibility "private") (not $User.UserRelationship.IsPrivateGranted)}}
<img class="is-rounded" src="/static/img/shy-private.png">
{{else if and (eq $User.ProfilePhoto.Visibility "friends") (not $User.UserRelationship.IsFriend)}}
<img class="is-rounded" src="/static/img/shy-friends.png">
{{else}}
<img class="is-rounded" src="{{PhotoURL $User.ProfilePhoto.CroppedFilename}}">
{{end}}
{{else}}
<img class="is-rounded" src="/static/img/shy.png">
{{end}}
</a>
</figure>
<!-- Username plus a comma if multiple -->
<a href="/u/{{$User.Username}}">
{{- $User.Username -}}
</a>{{if and (eq (len $Outer.LikeExample) 2) (not $Outer.LikeRemainder)}}
{{if eq $i 0}}
and
{{end}}
{{- else if gt (len $Outer.LikeExample) 1}},{{end}}
{{end}}
<!-- Others -->
{{if .LikeRemainder}}
and
<a
href="#"
onclick="ShowLikeModal('{{.LikeTableName}}', {{.LikeTableID}}); return false"
>
{{.LikeRemainder}} other{{Pluralize64 .LikeRemainder}}</a>.
2023-09-14 04:28:38 +00:00
{{end}}
</div>
{{end}}
{{end}}
{{define "like-modal"}}
<div id="like-modal-app">
<div class="modal vue-managed" :class="{'is-active': visible}">
<div class="modal-background" @click="visible=false"></div>
<div class="modal-content">
<div class="card">
<div class="card-header has-background-info">
<p class="card-header-title has-text-light">
<i class="fa fa-heart mr-2"></i> [[title]]
</p>
</div>
<div class="card-content">
<div v-if="busy">
<i class="fa fa-spinner fa-spin"></i> Loading likes...
</div>
<div v-else>
<p class="block">
Found [[ total ]] like[[ total === 1 ? '' : 's' ]]
(page [[ page ]] of [[ pages ]]).
</p>
<div class="columns is-multiline">
<div class="column is-one-third"
v-for="row in result">
<!-- Avatar -->
<figure class="image is-16x16 is-inline-block mr-2">
<a :href="'/u/'+row.username" class="has-text-dark">
<img class="is-rounded" :src="row.avatar">
</a>
</figure>
<!-- Username link -->
<a :href="'/u/'+row.username" target="_blank">[[ row.username ]]</a>
</div>
</div>
<!-- Pager buttons -->
<div class="columns is-mobile">
<div class="column is-narrow">
<button type="button" class="button"
@click="prevPage()"
:disabled="page <= 1">
Previous
</button>
</div>
<div class="column is-narrow">
<button type="button" class="button"
@click="nextPage()"
:disabled="page >= pages">
Next page
</button>
</div>
<div class="column has-text-right">
<button type="button" class="button is-primary"
@click="visible=false">
Close
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
// Implemented in Vue widget.
var ShowLikeModal = function(tableName, tableID) {};
const likeModalApp = Vue.createApp({
delimiters: ['[[', ']]'],
data() {
return {
visible: false,
title: "Likes",
busy: false,
tableName: "photos",
tableID: 0,
page: 1,
pages: 0,
total: 0,
result: [],
}
},
mounted() {
ShowLikeModal = this.ShowLikeModal;
},
methods: {
ShowLikeModal(tableName, tableID) {
this.tableName = tableName;
this.tableID = tableID;
this.visible = true;
this.page = 1;
this.get();
},
prevPage() {
this.page--;
if (this.page <= 1) {
this.page = 1;
}
this.get();
},
nextPage() {
this.page++;
this.get();
},
get() {
this.busy = true;
return fetch("/v1/likes/users?" + new URLSearchParams({
table_name: this.tableName,
table_id: this.tableID,
page: this.page,
}), {
method: "GET",
mode: "same-origin",
cache: "no-cache",
credentials: "same-origin",
})
.then((response) => response.json())
.then((data) => {
if (data.StatusCode !== 200) {
window.alert(data.data.error);
return;
}
let likes = data.data.likes;
this.pages = data.data.pages;
this.total = data.data.pager.Total;
this.result = likes;
}).catch(resp => {
window.alert(resp);
}).finally(() => {
this.busy = false;
});
},
},
});
likeModalApp.mount("#like-modal-app");
</script>
{{end}}