Server: Expose visibility on submission update page

Make submission next/previous buttons respect visibility
This commit is contained in:
asonix 2021-02-01 19:03:57 -06:00
parent 2a85cb6661
commit d3e62b7cd1
6 changed files with 120 additions and 27 deletions

View file

@ -927,16 +927,14 @@ impl ReportView {
} }
pub(crate) fn select(&self, loader: &ActixLoader) -> Select { pub(crate) fn select(&self, loader: &ActixLoader) -> Select {
let select = Select::new("action") Select::new("action")
.title(&fl!(loader, "admin-report-resolve-select")) .title(&fl!(loader, "admin-report-resolve-select"))
.options(&[ .options(&[
(&fl!(loader, "admin-report-ignore"), "Ignore"), (&fl!(loader, "admin-report-ignore"), "Ignore"),
(&fl!(loader, "admin-report-delete"), "Delete"), (&fl!(loader, "admin-report-delete"), "Delete"),
(&fl!(loader, "admin-report-suspend"), "Suspend"), (&fl!(loader, "admin-report-suspend"), "Suspend"),
]) ])
.default_option("Ignore"); .default_option("Ignore")
select
} }
pub(crate) fn input(&self, loader: &ActixLoader) -> TextInput { pub(crate) fn input(&self, loader: &ActixLoader) -> TextInput {

View file

@ -92,6 +92,7 @@ impl<'b> Pagination for BrowsePager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
false,
)), )),
) )
} }
@ -106,6 +107,7 @@ impl<'b> Pagination for BrowsePager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
false,
)), )),
) )
} }
@ -120,6 +122,7 @@ impl<'b> Pagination for BrowsePager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
false,
)), )),
) )
} }
@ -143,6 +146,7 @@ impl<'b> Pagination for DraftPager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
true,
)), )),
) )
} }
@ -157,6 +161,7 @@ impl<'b> Pagination for DraftPager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
true,
)), )),
) )
} }
@ -171,6 +176,7 @@ impl<'b> Pagination for DraftPager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
true,
)), )),
) )
} }
@ -194,6 +200,7 @@ impl<'b> Pagination for SubmissionPager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
true,
)), )),
) )
} }
@ -208,6 +215,7 @@ impl<'b> Pagination for SubmissionPager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
true,
)), )),
) )
} }
@ -222,6 +230,7 @@ impl<'b> Pagination for SubmissionPager<'b> {
self.viewer, self.viewer,
&self.store.store, &self.store.store,
self.cache, self.cache,
true,
)), )),
) )
} }
@ -231,6 +240,7 @@ fn filter_submissions<'a>(
viewer: Option<Uuid>, viewer: Option<Uuid>,
store: &'a hyaenidae_profiles::store::Store, store: &'a hyaenidae_profiles::store::Store,
cache: &'a mut Cache, cache: &'a mut Cache,
show_unlisted: bool,
) -> impl FnMut(Uuid) -> Option<Uuid> + 'a { ) -> impl FnMut(Uuid) -> Option<Uuid> + 'a {
move |submission_id| { move |submission_id| {
if !cache.submission_map.contains_key(&submission_id) { if !cache.submission_map.contains_key(&submission_id) {
@ -241,7 +251,7 @@ fn filter_submissions<'a>(
cache.profile_map.insert(profile.id(), profile); cache.profile_map.insert(profile.id(), profile);
} }
let opt = can_view(viewer, &submission, store, cache); let opt = can_view(viewer, &submission, store, cache, show_unlisted);
if let Some(file_id) = submission.files().get(0) { if let Some(file_id) = submission.files().get(0) {
if !cache.file_map.contains_key(file_id) { if !cache.file_map.contains_key(file_id) {
@ -256,7 +266,7 @@ fn filter_submissions<'a>(
} else { } else {
let submission = cache.submission_map.get(&submission_id)?.clone(); let submission = cache.submission_map.get(&submission_id)?.clone();
can_view(viewer, &submission, store, cache)?; can_view(viewer, &submission, store, cache, show_unlisted)?;
Some(submission_id) Some(submission_id)
} }
@ -268,8 +278,12 @@ pub(crate) fn can_view(
submission: &Submission, submission: &Submission,
store: &hyaenidae_profiles::store::Store, store: &hyaenidae_profiles::store::Store,
cache: &mut Cache, cache: &mut Cache,
show_unlisted: bool,
) -> Option<()> { ) -> Option<()> {
if let Some(viewer) = viewer { if let Some(viewer) = viewer {
if viewer == submission.profile_id() {
return Some(());
}
if let Some(block) = cache.blocks.get(&submission.profile_id()) { if let Some(block) = cache.blocks.get(&submission.profile_id()) {
if *block { if *block {
return None; return None;
@ -302,7 +316,7 @@ pub(crate) fn can_view(
} }
} }
if submission.is_followers_only() { if (submission.is_unlisted() && !show_unlisted) || submission.is_followers_only() {
if let Some(follow) = cache.follows.get(&submission.profile_id()) { if let Some(follow) = cache.follows.get(&submission.profile_id()) {
if !*follow { if !*follow {
return None; return None;
@ -323,6 +337,10 @@ pub(crate) fn can_view(
} }
} }
} else { } else {
if submission.is_unlisted() && !show_unlisted {
return None;
}
let requires_login = if let Some(profile) = cache.profile_map.get(&submission.profile_id()) let requires_login = if let Some(profile) = cache.profile_map.get(&submission.profile_id())
{ {
profile.login_required() profile.login_required()

View file

@ -9,8 +9,8 @@ use crate::{
ActixLoader, State, ActixLoader, State,
}; };
use actix_web::{client::Client, web, HttpRequest, HttpResponse, Scope}; use actix_web::{client::Client, web, HttpRequest, HttpResponse, Scope};
use hyaenidae_profiles::store::{File, Profile, Submission}; use hyaenidae_profiles::store::{File, Profile, Submission, Visibility};
use hyaenidae_toolkit::{Button, FileInput, TextInput, Tile}; use hyaenidae_toolkit::{Button, FileInput, Select, TextInput, Tile};
use i18n_embed_fl::fl; use i18n_embed_fl::fl;
use std::collections::HashMap; use std::collections::HashMap;
use uuid::Uuid; use uuid::Uuid;
@ -312,6 +312,17 @@ impl SubmissionState {
}) })
} }
pub(crate) fn visibility(&self, loader: &ActixLoader) -> Select {
Select::new("visibility")
.title(&fl!(loader, "submission-visibility-select"))
.options(&[
(&fl!(loader, "submission-visibility-followers"), "Followers"),
(&fl!(loader, "submission-visibility-unlisted"), "Unlisted"),
(&fl!(loader, "submission-visibility-public"), "Public"),
])
.default_option(&self.submission.visibility().to_string())
}
pub(crate) fn title_input(&self, loader: &ActixLoader) -> TextInput { pub(crate) fn title_input(&self, loader: &ActixLoader) -> TextInput {
TextInput::new("title") TextInput::new("title")
.title(&fl!(loader, "update-submission-title-input")) .title(&fl!(loader, "update-submission-title-input"))
@ -690,40 +701,90 @@ fn submission_nav(
} }
async fn adjacent_submissions( async fn adjacent_submissions(
submission_id: Uuid, viewer: Option<Uuid>,
is_published: bool, submission: &Submission,
state: &State, state: &State,
) -> Result<(Option<Uuid>, Option<Uuid>), Error> { ) -> Result<(Option<Uuid>, Option<Uuid>), Error> {
let submission_id = submission.id();
let is_published = submission.published().is_some();
let store = state.profiles.clone(); let store = state.profiles.clone();
let (next, prev) = web::block(move || { let (next, prev) = web::block(move || {
if is_published { if is_published {
let inner_store = store.clone();
let prev = store let prev = store
.store .store
.submissions .submissions
.published_newer_than_for_profile(submission_id) .published_newer_than_for_profile(submission_id)
.filter(|id| *id != submission_id) .filter(|id| *id != submission_id)
.next(); .find_map(move |id| {
let submission = inner_store.store.submissions.by_id(id).ok()??;
crate::pagination::submission::can_view(
viewer,
&submission,
&inner_store.store,
&mut Default::default(),
true,
)
.map(move |_| id)
});
let next = store let next = store
.store .store
.submissions .submissions
.published_older_than_for_profile(submission_id) .published_older_than_for_profile(submission_id)
.filter(|id| *id != submission_id) .filter(|id| *id != submission_id)
.next(); .find_map(move |id| {
let submission = store.store.submissions.by_id(id).ok()??;
crate::pagination::submission::can_view(
viewer,
&submission,
&store.store,
&mut Default::default(),
true,
)
.map(move |_| id)
});
Ok((next, prev)) as Result<_, Error> Ok((next, prev)) as Result<_, Error>
} else { } else {
let inner_store = store.clone();
let prev = store let prev = store
.store .store
.submissions .submissions
.drafted_newer_than_for_profile(submission_id) .drafted_newer_than_for_profile(submission_id)
.filter(|id| *id != submission_id) .filter(|id| *id != submission_id)
.next(); .find_map(move |id| {
let submission = inner_store.store.submissions.by_id(id).ok()??;
crate::pagination::submission::can_view(
viewer,
&submission,
&inner_store.store,
&mut Default::default(),
true,
)
.map(move |_| id)
});
let next = store let next = store
.store .store
.submissions .submissions
.drafted_older_than_for_profile(submission_id) .drafted_older_than_for_profile(submission_id)
.filter(|id| *id != submission_id) .filter(|id| *id != submission_id)
.next(); .find_map(move |id| {
let submission = store.store.submissions.by_id(id).ok()??;
crate::pagination::submission::can_view(
viewer,
&submission,
&store.store,
&mut Default::default(),
true,
)
.map(move |_| id)
});
Ok((next, prev)) as Result<_, Error> Ok((next, prev)) as Result<_, Error>
} }
@ -762,7 +823,7 @@ async fn submission_page(
} }
let (next_submission, previous_submission) = let (next_submission, previous_submission) =
adjacent_submissions(submission.id(), submission.published().is_some(), &state).await?; adjacent_submissions(viewer, &submission, &state).await?;
let (nav, current_file) = submission_nav( let (nav, current_file) = submission_nav(
page.map(|p| p.into_inner()), page.map(|p| p.into_inner()),
@ -895,7 +956,7 @@ async fn create_comment(
let cache = files_for_profile(&poster, cache, &state).await?; let cache = files_for_profile(&poster, cache, &state).await?;
let (next_submission, previous_submission) = let (next_submission, previous_submission) =
adjacent_submissions(submission.id(), submission.published().is_some(), &state).await?; adjacent_submissions(Some(profile.id()), &submission, &state).await?;
let (nav, current_file) = submission_nav( let (nav, current_file) = submission_nav(
page.map(|p| p.into_inner()), page.map(|p| p.into_inner()),
@ -932,6 +993,7 @@ async fn create_comment(
struct UpdateSubmissionForm { struct UpdateSubmissionForm {
title: String, title: String,
description: String, description: String,
visibility: Option<Visibility>,
} }
async fn update_submission( async fn update_submission(
@ -962,6 +1024,7 @@ async fn update_submission(
submission.id(), submission.id(),
form.title.clone(), form.title.clone(),
Some(form.description.clone()), Some(form.description.clone()),
form.visibility,
)) ))
.await; .await;

View file

@ -12,16 +12,18 @@
@(loader: &ActixLoader, browse_view: &ViewBrowseState, nav_state: &NavState) @(loader: &ActixLoader, browse_view: &ViewBrowseState, nav_state: &NavState)
@:wide(loader, &fl!(loader, "site-name"), &fl!(loader, "site-description"), nav_state, {}, { @:wide(loader, &fl!(loader, "site-name"), &fl!(loader, "site-description"), nav_state, {}, {
<div class="tabs"> @if browse_view.is_logged_in() {
@:tab_group({ <div class="tabs">
@:tab(Tab::new("/browse").selected(true), { @:tab_group({
@fl!(loader, "submissions-tab") @:tab(Tab::new("/browse").selected(true), {
@fl!(loader, "submissions-tab")
})
@:tab(Tab::new("/discover"), {
@fl!(loader, "profiles-tab")
})
}) })
@:tab(Tab::new("/discover"), { </div>
@fl!(loader, "profiles-tab") }
})
})
</div>
@if browse_view.has_submissions() { @if browse_view.has_submissions() {
@if browse_view.has_nav() { @if browse_view.has_nav() {
@:thumbnail_border({ @:thumbnail_border({

View file

@ -1,7 +1,11 @@
@use crate::ActixLoader; @use crate::ActixLoader;
@use crate::templates::{button_js, file_js}; @use crate::templates::{button_js, file_js};
@use crate::{templates::layouts::home, nav::NavState, submissions::SubmissionState}; @use crate::{templates::layouts::home, nav::NavState, submissions::SubmissionState};
@use hyaenidae_toolkit::{templates::{button_group, card, card_body, card_title, file_input, text_input}, Button, Card}; @use hyaenidae_toolkit::{templates::{button_group}, Button};
@use hyaenidae_toolkit::{templates::{card, card_body, card_title}, Card};
@use hyaenidae_toolkit::templates::file_input;
@use hyaenidae_toolkit::templates::select;
@use hyaenidae_toolkit::templates::text_input;
@use hyaenidae_toolkit::templates::image; @use hyaenidae_toolkit::templates::image;
@use i18n_embed_fl::fl; @use i18n_embed_fl::fl;
@ -39,6 +43,9 @@
@:card_body({ @:card_body({
@:text_input(&state.title_input(loader).dark(nav_state.dark())) @:text_input(&state.title_input(loader).dark(nav_state.dark()))
@:text_input(&state.description_input(loader).dark(nav_state.dark())) @:text_input(&state.description_input(loader).dark(nav_state.dark()))
@if !state.is_published() {
@:select(&state.visibility(loader).dark(nav_state.dark()))
}
}) })
@:card_body({ @:card_body({
@:button_group(&[ @:button_group(&[

View file

@ -169,6 +169,11 @@ create-submission-heading = Select a file to post
create-submission-input = Select Image create-submission-input = Select Image
create-submission-button = Next create-submission-button = Next
submission-visibility-select = Visibility
submission-visibility-followers = Followers Only
submission-visibility-unlisted = Unlisted
submission-visibility-public = Public
update-submission-title = Edit Submission update-submission-title = Edit Submission
update-submission-subtitle = Edit information or update images update-submission-subtitle = Edit information or update images
update-submission-publish-title = Publish Submission update-submission-publish-title = Publish Submission