Create sidebar layout component

This commit is contained in:
silverpill 2022-07-29 18:12:10 +00:00
parent 4876b7b439
commit b0a5fac22a
17 changed files with 171 additions and 159 deletions

View file

@ -20,7 +20,7 @@
</div>
</div>
</header>
<router-view :key="route.fullPath" :class="{ wide: isPublicPage() }" />
<router-view :key="route.fullPath" />
</template>
<script setup lang="ts">

View file

@ -0,0 +1,22 @@
<template>
<div id="main" :class="{ wide: currentUser === null }">
<div class="content">
<slot name="content"></slot>
</div>
<sidebar></sidebar>
</div>
</template>
<script setup lang="ts">
import { $ } from "vue/macros"
import { useCurrentUser } from "@/store/user"
import Sidebar from "./Sidebar.vue"
const { currentUser } = $(useCurrentUser())
</script>
<style scoped lang="scss">
@import "../styles/layout";
@import "../styles/theme";
</style>

View file

@ -1,17 +1,16 @@
<template>
<div id="main">
<div class="content about" v-if="instance">
<sidebar-layout>
<template #content v-if="instance">
<h1>{{ instance.title }}</h1>
<div class="description static-text" v-html="renderMarkdown(instance.description)"></div>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
import { $ } from "vue/macros"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useInstanceInfo } from "@/store/instance"
import { renderMarkdown } from "@/utils/markdown"

View file

@ -1,5 +1,5 @@
<template>
<static-page v-if="instance">
<static-page v-if="instance" class="wide">
<template #heading>{{ instance.title }}</template>
<template #text>
<div v-html="renderMarkdown(instance.description)"></div>

View file

@ -1,5 +1,5 @@
<template>
<static-page>
<static-page class="wide">
<template #heading>Ethereum</template>
<template #text>
<div v-html="text"></div>

View file

@ -1,11 +1,10 @@
<template>
<div id="main">
<div class="content posts">
<sidebar-layout>
<template #content>
<post-editor @post-created="insertPost"></post-editor>
<post-list :posts="posts" @load-next-page="loadNextPage"></post-list>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -15,7 +14,7 @@ import { $ref } from "vue/macros"
import { Post, getHomeTimeline } from "@/api/posts"
import PostEditor from "@/components/PostEditor.vue"
import PostList from "@/components/PostList.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
const { ensureAuthToken } = useCurrentUser()

View file

@ -1,5 +1,5 @@
<template>
<div class="landing-page">
<div class="landing-page wide">
<div class="instance-group">
<div v-if="instance" class="instance-info">
<h1 class="instance-title">{{ instance.title }}</h1>

View file

@ -1,6 +1,6 @@
<template>
<div id="main">
<div class="content">
<sidebar-layout>
<template #content>
<div
class="notification"
v-for="(notification, index) in notifications"
@ -84,9 +84,8 @@
>
Show more notifications
</button>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -97,7 +96,7 @@ import { updateNotificationMarker } from "@/api/markers"
import { getNotifications, Notification } from "@/api/notifications"
import Avatar from "@/components/Avatar.vue"
import Post from "@/components/Post.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useInstanceInfo } from "@/store/instance"
import { useNotifications } from "@/store/notifications"
import { useCurrentUser } from "@/store/user"

View file

@ -1,9 +1,9 @@
<template>
<div id="main" ref="containerRef">
<div v-if="!isLoading && thread.length === 0" class="content not-found">
Not found
</div>
<div v-else class="content posts">
<sidebar-layout>
<template #content>
<div v-if="!isLoading && thread.length === 0" class="not-found">
Not found
</div>
<post
v-for="(post, index) in thread"
:key="post.id"
@ -15,9 +15,8 @@
@comment-created="onCommentCreated(index, $event)"
@post-deleted="onPostDeleted(index)"
></post>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -27,7 +26,7 @@ import { useRoute } from "vue-router"
import { Post as PostObject, getPostContext } from "@/api/posts"
import Post from "@/components/Post.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
const route = useRoute()
@ -37,7 +36,6 @@ let selectedId = $ref(route.params.postId as string)
let highlightedId = $ref<string | null>(null)
let thread = $ref<PostObject[]>([])
let isLoading = $ref(true)
const containerRef = $ref<HTMLElement | null>(null)
const loader = $ref(getPostContext(authToken, selectedId))
onMounted(async () => {
@ -58,11 +56,12 @@ onMounted(async () => {
})
function scrollTo(postId: string, options: any = {}) {
if (containerRef === null) {
const container = document.getElementById("main")
if (!container) {
return
}
const containerOffset = containerRef.offsetTop // sticky header height or top margin
const postElem: HTMLElement | null = containerRef.querySelector(`div[data-post-id="${postId}"]`)
const containerOffset = container.offsetTop // sticky header height or top margin
const postElem: HTMLElement | null = container.querySelector(`div[data-post-id="${postId}"]`)
if (postElem === null) {
return
}

View file

@ -1,5 +1,5 @@
<template>
<div v-if="post && token" class="post-overlay">
<div v-if="post && token" class="post-overlay wide">
<div v-if="canGoBack()" class="back-btn-wrapper">
<a class="back-btn" title="Back" @click="goBack()">
<img :src="require('@/assets/feather/arrow-left.svg')">

View file

@ -1,6 +1,6 @@
<template>
<div id="main" v-if="profile">
<div class="content posts">
<sidebar-layout v-if="profile">
<template #content>
<div class="profile-block">
<div class="profile-header">
<img v-if="profile.header" :src="profile.header">
@ -180,9 +180,8 @@
:key="profile.id"
></profile-list-item>
</template>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -210,7 +209,7 @@ import {
import Avatar from "@/components/Avatar.vue"
import PostList from "@/components/PostList.vue"
import ProfileListItem from "@/components/ProfileListItem.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { BACKEND_URL } from "@/constants"
import { useInstanceInfo } from "@/store/instance"
import { useCurrentUser } from "@/store/user"

View file

@ -1,14 +1,16 @@
<template>
<div id="main">
<div class="content profile-list">
<router-link
v-for="profile in profiles"
class="profile-list-item"
:to="{ name: 'profile', params: { profileId: profile.id }}"
:key="profile.id"
>
<profile-card :profile="profile" :compact="false"></profile-card>
</router-link>
<sidebar-layout>
<template #content>
<div class="profile-grid">
<router-link
v-for="profile in profiles"
class="profile-list-item"
:to="{ name: 'profile', params: { profileId: profile.id }}"
:key="profile.id"
>
<profile-card :profile="profile" :compact="false"></profile-card>
</router-link>
</div>
<button
v-if="isPageFull()"
class="btn secondary next-btn"
@ -16,9 +18,8 @@
>
Show more profiles
</button>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -28,7 +29,7 @@ import { $ref } from "vue/macros"
import { PAGE_SIZE } from "@/api/common"
import { Profile, getProfiles } from "@/api/users"
import ProfileCard from "@/components/ProfileCard.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
const { ensureAuthToken } = useCurrentUser()
@ -61,7 +62,7 @@ async function loadNextPage() {
@import "../styles/layout";
@import "../styles/theme";
.profile-list {
.profile-grid {
display: grid;
gap: $block-outer-padding;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

View file

@ -1,84 +1,85 @@
<template>
<div id="main">
<form class="content settings" @submit.prevent="save()">
<h1>Edit profile</h1>
<div class="input-group">
<label for="display-name">Display name</label>
<input id="display-name" v-model.trim="form.display_name">
</div>
<div class="input-group">
<label for="bio">Bio</label>
<textarea
id="bio"
ref="bioInputRef"
:value="form.note_source || ''"
@input="onBioUpdate($event)"
></textarea>
</div>
<div class="image-upload-group">
<profile-card :profile="profilePreview" :compact="true"></profile-card>
<div class="image-upload-inputs">
<div class="input-group">
<label for="avatar">Avatar</label>
<input
type="file"
id="avatar"
accept="image/*"
@change="onFilePicked('avatar', $event)"
>
</div>
<div class="input-group">
<label for="banner">Banner</label>
<input
type="file"
id="banner"
accept="image/*"
@change="onFilePicked('header', $event)"
>
<sidebar-layout>
<template #content>
<form @submit.prevent="save()">
<h1>Edit profile</h1>
<div class="input-group">
<label for="display-name">Display name</label>
<input id="display-name" v-model.trim="form.display_name">
</div>
<div class="input-group">
<label for="bio">Bio</label>
<textarea
id="bio"
ref="bioInputRef"
:value="form.note_source || ''"
@input="onBioUpdate($event)"
></textarea>
</div>
<div class="image-upload-group">
<profile-card :profile="profilePreview" :compact="true"></profile-card>
<div class="image-upload-inputs">
<div class="input-group">
<label for="avatar">Avatar</label>
<input
type="file"
id="avatar"
accept="image/*"
@change="onFilePicked('avatar', $event)"
>
</div>
<div class="input-group">
<label for="banner">Banner</label>
<input
type="file"
id="banner"
accept="image/*"
@change="onFilePicked('header', $event)"
>
</div>
</div>
</div>
</div>
<div class="extra-fields input-group">
<label>
Additional info
<div class="sub-label">You can have up to {{ extraFieldMaxCount }} items displayed as a table on your profile</div>
</label>
<div
v-for="(field, index) in form.fields_attributes"
:key="index"
class="extra-field"
:class="{'error': !isValidExtraField(index)}"
>
<input v-model.trim="field.name" placeholder="Label">
<input
:value="field.value_source"
@input="onExtraFieldUpdate(field, $event)"
placeholder="Content"
<div class="extra-fields input-group">
<label>
Additional info
<div class="sub-label">You can have up to {{ extraFieldMaxCount }} items displayed as a table on your profile</div>
</label>
<div
v-for="(field, index) in form.fields_attributes"
:key="index"
class="extra-field"
:class="{'error': !isValidExtraField(index)}"
>
<a
class="remove-extra-field"
title="Remove item"
@click="removeExtraField(index)"
<input v-model.trim="field.name" placeholder="Label">
<input
:value="field.value_source"
@input="onExtraFieldUpdate(field, $event)"
placeholder="Content"
>
<a
class="remove-extra-field"
title="Remove item"
@click="removeExtraField(index)"
>
<img :src="require('@/assets/feather/x-circle.svg')">
</a>
</div>
<button
v-if="form.fields_attributes.length <= extraFieldMaxCount"
type="button"
class="add-extra-field"
@click="addExtraField()"
>
<img :src="require('@/assets/feather/x-circle.svg')">
</a>
<img :src="require('@/assets/feather/plus-circle.svg')">
Add new item
</button>
</div>
<button
v-if="form.fields_attributes.length <= extraFieldMaxCount"
type="button"
class="add-extra-field"
@click="addExtraField()"
>
<img :src="require('@/assets/feather/plus-circle.svg')">
Add new item
<button type="submit" class="btn" :disabled="!isFormValid()">
Save
</button>
</div>
<button type="submit" class="btn" :disabled="!isFormValid()">
Save
</button>
</form>
<sidebar></sidebar>
</div>
</form>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -93,7 +94,7 @@ import {
updateProfile,
} from "@/api/users"
import ProfileCard from "@/components/ProfileCard.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
import { setupAutoResize } from "@/utils/autoresize"
import { renderMarkdownLite } from "@/utils/markdown"

View file

@ -1,10 +1,9 @@
<template>
<div id="main">
<div class="content posts">
<sidebar-layout>
<template #content>
<post-list :posts="posts" @load-next-page="loadNextPage"></post-list>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -13,7 +12,7 @@ import { $ref } from "vue/macros"
import { Post, getPublicTimeline } from "@/api/posts"
import PostList from "@/components/PostList.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
const { ensureAuthToken } = useCurrentUser()
@ -30,6 +29,3 @@ async function loadNextPage(maxId: string) {
posts.push(...nextPage)
}
</script>
<style scoped lang="scss">
</style>

View file

@ -1,6 +1,6 @@
<template>
<div id="main">
<div class="content search-result-group">
<sidebar-layout>
<template #content>
<loader v-if="isLoading"></loader>
<div v-if="!isLoading" class="search-message">
<template v-if="errorMessage">{{ errorMessage }}</template>
@ -20,9 +20,8 @@
:key="post.id"
></post>
</div>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -36,7 +35,7 @@ import { Profile } from "@/api/users"
import Loader from "@/components/Loader.vue"
import Post from "@/components/Post.vue"
import ProfileListItem from "@/components/ProfileListItem.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
const route = useRoute()

View file

@ -1,13 +1,12 @@
<template>
<div id="main" v-if="profile && isLocalUser()">
<div class="content">
<sidebar-layout v-if="profile && isLocalUser()">
<template #content>
<component
:is="isCurrentUser() ? SubscriptionSetup : Subscription"
:profile="profile"
></component>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -16,7 +15,7 @@ import { $, $ref } from "vue/macros"
import { useRoute } from "vue-router"
import { getProfile, Profile } from "@/api/users"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import Subscription from "@/components/Subscription.vue"
import SubscriptionSetup from "@/components/SubscriptionSetup.vue"
import { useCurrentUser } from "@/store/user"

View file

@ -1,13 +1,12 @@
<template>
<div id="main">
<div class="content posts">
<sidebar-layout>
<template #content>
<post-list
:posts="posts"
@load-next-page="loadNextPage"
></post-list>
</div>
<sidebar></sidebar>
</div>
</template>
</sidebar-layout>
</template>
<script setup lang="ts">
@ -16,7 +15,7 @@ import { useRoute } from "vue-router"
import { Post, getTagTimeline } from "@/api/posts"
import PostList from "@/components/PostList.vue"
import Sidebar from "@/components/Sidebar.vue"
import SidebarLayout from "@/components/SidebarLayout.vue"
import { useCurrentUser } from "@/store/user"
const route = useRoute()