210 lines
7.5 KiB
HTML
210 lines
7.5 KiB
HTML
<!-- "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>.
|
|
{{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}}
|