New collections (#1484)

* [WIP] Transfer collections to own branch

* fixes

* rewrite js

* Add visibility dropdown to collection edit modal

* Add visibility badges to collection page

* Update visibility options and icons in collection
page

* Add delete functionality to collection modal

* Collection project deletion flow

* remove "visit project" button on overflow

* Remove via checklist not individually

* Update manage title in settings.vue

* remove collections from settings page

* hook up collections page

* collection header to look like project header

* Refactor layout.scss and collections.vue

* fix omorphia

* Update

* Conform collections to old design structure

* Update navigation links and remove unused code

* Add collection view and collections to user page

* Refactor user project display logic

* Add collection creation functionality and update profile labels

* Add function calls to initialize user collections

* Refactor collection page layout and functionality

* Add initialization of user collections in create function

* Fix styling issue in collection page

* Update collection status to private

* remove name

* Refactor card component and update grid layout

* Finish collections

---------

Co-authored-by: Carter <safe@fea.st>
This commit is contained in:
Geometrically
2023-12-27 13:27:50 -05:00
committed by GitHub
parent e319d19a54
commit 3a735ea0ce
24 changed files with 1396 additions and 123 deletions

View File

@@ -140,6 +140,7 @@
<div class="markdown-body" v-html="renderString(licenseText)" />
</div>
</Modal>
<CollectionCreateModal ref="modal_collection" :project-ids="[project.id]" />
<div
:class="{
'normal-page': true,
@@ -214,6 +215,7 @@
/>
</Categories>
<hr class="card-divider" />
<div class="primary-stat">
<DownloadIcon class="primary-stat__icon" aria-hidden="true" />
<div class="primary-stat__text">
@@ -223,6 +225,7 @@
download<span v-if="project.downloads !== 1">s</span>
</div>
</div>
<div class="primary-stat">
<HeartIcon class="primary-stat__icon" aria-hidden="true" />
<div class="primary-stat__text">
@@ -262,13 +265,9 @@
<hr class="card-divider" />
<div class="input-group">
<template v-if="auth.user">
<button class="iconified-button" @click="() => reportProject(project.id)">
<ReportIcon aria-hidden="true" />
Report
</button>
<button
v-if="!user.follows.find((x) => x.id === project.id)"
class="iconified-button"
class="btn"
@click="userFollowProject(project)"
>
<HeartIcon aria-hidden="true" />
@@ -276,12 +275,59 @@
</button>
<button
v-if="user.follows.find((x) => x.id === project.id)"
class="iconified-button"
class="btn"
@click="userUnfollowProject(project)"
>
<HeartIcon fill="currentColor" aria-hidden="true" />
Unfollow
</button>
<PopoutMenu class="btn" direction="right" position="bottom" from="top-right">
<BookmarkIcon aria-hidden="true" />
Save
<template #menu>
<input
v-model="displayCollectionsSearch"
type="text"
placeholder="Search collections..."
class="search-input menu-search"
/>
<div v-if="collections.length > 0" class="collections-list">
<Checkbox
v-for="option in collections"
:key="option.id"
:model-value="option.projects.includes(project.id)"
class="popout-checkbox"
@update:model-value="userCollectProject(option, project.id)"
>
{{ option.name }}
</Checkbox>
</div>
<div v-else class="menu-text">
<p class="popout-text">No collections found.</p>
</div>
<button class="btn collection-button" @click="$refs.modal_collection.show()">
<PlusIcon />
Create new collection
</button>
</template>
</PopoutMenu>
<OverflowMenu
class="btn icon-only"
:options="[
{
id: 'report',
action: () => reportProject(project.id),
color: 'red',
hoverOnly: true,
},
{ id: 'copy-id', action: () => copyId() },
]"
direction="right"
>
<MoreHorizontalIcon />
<template #report> <ReportIcon /> Report</template>
<template #copy-id> <ClipboardCopyIcon /> Copy ID</template>
</OverflowMenu>
</template>
<template v-else>
<nuxt-link class="iconified-button" to="/auth/sign-in">
@@ -292,6 +338,24 @@
<HeartIcon aria-hidden="true" />
Follow
</nuxt-link>
<OverflowMenu
class="btn icon-only"
:options="[
{
id: 'report',
action: () => navigateTo('/auth/sign-in'),
color: 'red',
hoverOnly: true,
},
{ id: 'copy-id', action: () => copyId() },
]"
direction="right"
>
<MoreHorizontalIcon />
<template #report> <ReportIcon /> Report</template>
<template #copy-id> <ClipboardCopyIcon /> Copy ID</template>
</OverflowMenu>
</template>
</div>
</div>
@@ -668,7 +732,17 @@
</div>
</template>
<script setup>
import { Promotion, ChartIcon } from 'omorphia'
import {
Promotion,
OverflowMenu,
PopoutMenu,
BookmarkIcon,
MoreHorizontalIcon,
ClipboardCopyIcon,
PlusIcon,
Checkbox,
ChartIcon,
} from 'omorphia'
import CalendarIcon from '~/assets/images/utils/calendar.svg'
import ClearIcon from '~/assets/images/utils/clear.svg'
import DownloadIcon from '~/assets/images/utils/download.svg'
@@ -711,6 +785,8 @@ import VersionIcon from '~/assets/images/utils/version.svg'
import { renderString } from '~/helpers/parse.js'
import { reportProject } from '~/utils/report-helpers.ts'
import Breadcrumbs from '~/components/ui/Breadcrumbs.vue'
import { userCollectProject } from '~/composables/user.js'
import CollectionCreateModal from '~/components/ui/CollectionCreateModal.vue'
const data = useNuxtApp()
const route = useRoute()
@@ -721,6 +797,15 @@ const user = await useUser()
const cosmetics = useCosmetics()
const tags = useTags()
const displayCollectionsSearch = ref('')
const collections = computed(() =>
user.value && user.value.collections
? user.value.collections.filter((x) =>
x.name.toLowerCase().includes(displayCollectionsSearch.value.toLowerCase())
)
: []
)
if (
!route.params.id ||
!(
@@ -1132,7 +1217,6 @@ const collapsedChecklist = ref(false)
}
.project__header {
overflow: hidden;
.project__gallery {
display: none;
}
@@ -1141,11 +1225,12 @@ const collapsedChecklist = ref(false)
display: inline-block;
width: 100%;
height: 10rem;
background-color: var(--color-button-bg-active);
img {
width: 100%;
height: 10rem;
object-fit: cover;
background-color: var(--color-button-bg-active);
border-radius: var(--size-rounded-card) var(--size-rounded-card) 0 0;
}
}
.project__icon {
@@ -1160,6 +1245,9 @@ const collapsedChecklist = ref(false)
background: none;
border-radius: unset;
}
.input-group {
flex-wrap: nowrap;
}
}
.project-info {
@@ -1367,4 +1455,44 @@ const collapsedChecklist = ref(false)
.normal-page__sidebar .mod-button {
margin-top: var(--spacing-card-sm);
}
.popout-checkbox {
padding: var(--gap-sm) var(--gap-md);
white-space: nowrap;
&:hover {
filter: brightness(0.95);
}
}
.popout-heading {
padding: var(--gap-sm) var(--gap-md);
padding-bottom: 0;
font-size: var(--font-size-nm);
color: var(--color-secondary);
}
.collection-button {
margin: var(--gap-sm) var(--gap-md);
white-space: nowrap;
}
.menu-text {
padding: 0 var(--gap-md);
font-size: var(--font-size-nm);
color: var(--color-secondary);
}
.menu-search {
margin: var(--gap-sm) var(--gap-md);
width: calc(100% - var(--gap-md) * 2);
}
.collections-list {
max-height: 40rem;
overflow-y: auto;
background-color: var(--color-bg);
border-radius: var(--radius-md);
margin: var(--gap-sm) var(--gap-md);
padding: var(--gap-sm);
}
</style>

View File

@@ -288,10 +288,10 @@ import {
ImageIcon,
TransferIcon,
ConfirmModal,
Modal,
FileInput,
DropArea,
} from 'omorphia'
import Modal from '~/components/ui/Modal.vue'
const props = defineProps({
project: {