Add page to view all projects of a user / group (#741)

* ReposOwner view

shows all repos owned by a person or organization
uses /:repoOwner urls (e. g. ci.example.org/example-org)
also includes a link from the repo page to the owner page
related to #468

* ReposOwner remove add btn; msg if no projects; grid

implements the changes suggested by @anbraten:
- removed the `add repository` button
- now shows a message `This organization / user does not have any projects yet.`
  when appropriate

now uses `grid` instead of `flex` on desktop to keep the search bar
centered and always in the same place
This commit is contained in:
valentinleistner 2022-02-06 20:59:45 +01:00 committed by GitHub
parent dbd048c5e9
commit 6bb964921e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 3 deletions

View file

@ -21,6 +21,13 @@ const routes: RouteRecordRaw[] = [
component: (): Component => import('~/views/RepoAdd.vue'),
meta: { authentication: 'required' },
},
{
path: '/:repoOwner',
name: 'repos-owner',
component: (): Component => import('~/views/ReposOwner.vue'),
props: true,
meta: { authentication: 'required' },
},
{
path: '/:repoOwner/:repoName',
name: 'repo-wrapper',

View file

@ -1,8 +1,8 @@
<template>
<FluidContainer class="flex flex-col">
<div class="flex flex-row flex-wrap border-b pb-4 mb-4 items-center dark:border-dark-200">
<div class="flex flex-row flex-wrap md:grid md:grid-cols-3 border-b pb-4 mb-4 dark:border-dark-200">
<h1 class="text-xl text-gray-500">Repositories</h1>
<TextField v-model="search" class="w-auto md:ml-auto" placeholder="Search ..." />
<TextField v-model="search" class="w-auto md:ml-auto md:mr-auto" placeholder="Search ..." />
<Button class="md:ml-auto" :to="{ name: 'repo-add' }" start-icon="plus" text="Add repository" />
</div>

View file

@ -0,0 +1,64 @@
<template>
<FluidContainer class="flex flex-col">
<div class="flex flex-row flex-wrap md:grid md:grid-cols-3 border-b pb-4 mb-4 dark:border-dark-200">
<h1 class="text-xl text-gray-500">{{ repoOwner }}</h1>
<TextField v-model="search" class="w-auto md:ml-auto md:mr-auto" placeholder="Search ..." />
</div>
<div class="space-y-4">
<ListItem
v-for="repo in searchedRepos"
:key="repo.id"
clickable
@click="$router.push({ name: 'repo', params: { repoName: repo.name, repoOwner: repo.owner } })"
>
<span class="text-gray-500">{{ `${repo.name}` }}</span>
</ListItem>
</div>
<div v-if="(searchedRepos || []).length <= 0" class="text-center">
<span class="text-gray-500 m-auto">This organization / user does not have any projects yet.</span>
</div>
</FluidContainer>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref } from 'vue';
import ListItem from '~/components/atomic/ListItem.vue';
import TextField from '~/components/form/TextField.vue';
import FluidContainer from '~/components/layout/FluidContainer.vue';
import { useRepoSearch } from '~/compositions/useRepoSearch';
import RepoStore from '~/store/repos';
export default defineComponent({
name: 'ReposOwner',
components: {
FluidContainer,
ListItem,
TextField,
},
props: {
repoOwner: {
type: String,
required: true,
},
},
setup(props) {
const repoStore = RepoStore();
// TODO: filter server side
const repos = computed(() => Object.values(repoStore.repos).filter((v) => v.owner === props.repoOwner));
const search = ref('');
const { searchedRepos } = useRepoSearch(repos, search);
onMounted(async () => {
await repoStore.loadRepos();
});
return { searchedRepos, search };
},
});
</script>

View file

@ -2,7 +2,8 @@
<FluidContainer v-if="repo && repoPermissions && $route.meta.repoHeader">
<div class="flex flex-wrap border-b items-center pb-4 mb-4 dark:border-gray-600 justify-center">
<h1 class="text-xl text-gray-500 w-full md:w-auto text-center mb-4 md:mb-0">
{{ `${repo.owner} / ${repo.name}` }}
<router-link :to="{ name: 'repos-owner', params: { repoOwner } }">{{ repoOwner }}</router-link>
{{ ` / ${repo.name}` }}
</h1>
<a v-if="badgeUrl" :href="badgeUrl" target="_blank" class="md:ml-auto">
<img :src="badgeUrl" />