-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: List team resources in related resources panel
Signed-off-by: Julius Härtl <[email protected]>
- Loading branch information
1 parent
89ba71e
commit 146908c
Showing
3 changed files
with
321 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
293 changes: 293 additions & 0 deletions
293
src/components/NcRelatedResourcesPanel/NcTeamResources.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
<template> | ||
<div v-if="appEnabled && isVisible" class="related-resources__team"> | ||
<div class="related-resources__header"> | ||
<h5>{{ t('Related team resources') }}</h5> | ||
</div> | ||
<div v-for="team in teamResources" | ||
:key="team.teamId" | ||
class="related-team" | ||
:class="{ 'related-team__open': open(team.teamId) }"> | ||
<h5 class="related-team__header"> | ||
<a class="related-team__link" @click="toggleOpen(team.teamId)"> | ||
<AccountGroup :size="20" /> | ||
{{ team.displayName }} | ||
</a> | ||
<NcActions> | ||
<NcActionLink :href="team.link" :label="t('View team')"> | ||
<template #icon> | ||
<OpenInNew :size="20" /> | ||
</template> | ||
</NcActionLink> | ||
</NcActions> | ||
<NcButton type="tertiary" @click.stop="toggleOpen(team.teamId)"> | ||
<ChevronUp v-if="open(team.teamId)" | ||
:size="20" /> | ||
<ChevronDown v-else | ||
:size="20" /> | ||
</NcButton> | ||
</h5> | ||
|
||
<div v-if="open(team.teamId)"> | ||
<div v-for="provider in teamProviders(team.teamId)" | ||
:key="provider.id" | ||
class="related-team-provider"> | ||
<h6 v-if="provider.resources.length > 0"> | ||
{{ provider.name }} | ||
</h6> | ||
<ul> | ||
<li v-for="resource in provider.resources" :key="resource.url" class="related-team-resource"> | ||
<a :href="resource.url" class="related-team-resource__link"> | ||
<span v-if="resource.iconEmoji" class="resource__icon"> | ||
{{ resource.iconEmoji }} | ||
</span> | ||
<NcIconSvgWrapper v-else-if="resource.iconSvg" | ||
class="resource__icon" | ||
:svg="resource.iconSvg" | ||
:size="20" /> | ||
<span v-if="resource.iconUrl" class="resource__icon"> | ||
<img :src="resource.iconURL" alt=""> | ||
</span> | ||
<span class="resource__name"> | ||
{{ resource.label }} | ||
</span> | ||
</a> | ||
</li> | ||
</ul> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import axios from '@nextcloud/axios' | ||
import { generateOcsUrl } from '@nextcloud/router' | ||
import AccountGroup from 'vue-material-design-icons/AccountGroup.vue' | ||
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue' | ||
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue' | ||
import OpenInNew from 'vue-material-design-icons/OpenInNew.vue' | ||
import NcButton from '../NcButton/NcButton.vue' | ||
import NcActions from '../NcActions/NcActions.vue' | ||
import NcActionLink from '../NcActionLink/NcActionLink.vue' | ||
import NcIconSvgWrapper from '../NcIconSvgWrapper/NcIconSvgWrapper.vue' | ||
import { t } from '../../l10n.js' | ||
export default { | ||
name: 'NcTeamResources', | ||
components: { | ||
AccountGroup, | ||
ChevronDown, | ||
ChevronUp, | ||
OpenInNew, | ||
NcButton, | ||
NcActions, | ||
NcActionLink, | ||
NcIconSvgWrapper, | ||
}, | ||
props: { | ||
providerId: { | ||
type: String, | ||
default: null, | ||
}, | ||
itemId: { | ||
type: [String, Number], | ||
default: null, | ||
}, | ||
resourceType: { | ||
type: String, | ||
default: '', | ||
}, | ||
/** | ||
* Set the maximum number of resources to load | ||
*/ | ||
limit: { | ||
type: Number, | ||
default: 0, | ||
}, | ||
/** | ||
* Only used by the files sidebar | ||
* | ||
* File info is passed when registered with `OCA.Sharing.ShareTabSections.registerSection()` | ||
*/ | ||
fileInfo: { | ||
type: Object, | ||
default: null, | ||
}, | ||
/** | ||
* Make the header name dynamic | ||
*/ | ||
header: { | ||
type: String, | ||
default: t('Related resources'), | ||
}, | ||
headerOther: { | ||
type: String, | ||
default: t('Other resources'), | ||
}, | ||
description: { | ||
type: String, | ||
default: t('Anything shared with the same group of people will show up here'), | ||
}, | ||
/** | ||
* If this element is used on a primary element set to true for primary styling. | ||
*/ | ||
primary: { | ||
type: Boolean, | ||
default: false, | ||
}, | ||
}, | ||
data() { | ||
return { | ||
appEnabled: OC?.appswebroots?.circles !== undefined && (OC.config.version.split('.')[0] ?? 0) >= 29, | ||
loading: false, | ||
error: null, | ||
teamResources: null, | ||
teamOpen: null, | ||
} | ||
}, | ||
computed: { | ||
isVisible() { | ||
return !this.loading && this.error === null && this.teamResources?.length > 0 | ||
}, | ||
teamProviders() { | ||
return (teamId) => { | ||
const team = this.teamResources.find(t => t.teamId === teamId) | ||
return team.resources?.reduce((acc, resource) => { | ||
if (resource.provider.id === this.providerId && resource.id === String(this.itemId)) { | ||
return acc | ||
} | ||
if (!acc[resource.provider.id]) { | ||
acc[resource.provider.id] = resource.provider | ||
acc[resource.provider.id].resources = [] | ||
} | ||
if (resource.provider.id === this.providerId && resource.id === String(this.itemId)) { | ||
return acc | ||
} | ||
acc[resource.provider.id].resources.push(resource) | ||
return acc | ||
}, {}) | ||
} | ||
}, | ||
open() { | ||
return (teamId) => { | ||
return this.teamOpen === teamId | ||
} | ||
}, | ||
}, | ||
watch: { | ||
providerId() { | ||
this.fetchTeamResources() | ||
}, | ||
itemId() { | ||
this.fetchTeamResources() | ||
}, | ||
}, | ||
created() { | ||
this.fetchTeamResources() | ||
}, | ||
methods: { | ||
t, | ||
async fetchTeamResources() { | ||
try { | ||
const response = await axios.get(generateOcsUrl(`/teams/resources/${this.providerId}/${this.itemId}`)) | ||
this.error = null | ||
this.teamResources = response.data.ocs.data.teams | ||
this.teamOpen = this.teamResources[0]?.teamId | ||
} catch (e) { | ||
this.error = e | ||
console.error(e) | ||
} finally { | ||
this.loading = false | ||
} | ||
}, | ||
toggleOpen(teamId) { | ||
this.teamOpen = this.teamOpen !== teamId ? teamId : null | ||
}, | ||
}, | ||
} | ||
</script> | ||
<style lang="scss" scoped> | ||
h5 { | ||
font-weight: bold; | ||
margin-bottom: 6px; | ||
} | ||
.related-team { | ||
border-radius: var(--border-radius-rounded); | ||
border: 2px solid var(--color-border-dark); | ||
margin-bottom: 6px; | ||
&__open { | ||
border-color: var(--color-primary-element); | ||
} | ||
&__header { | ||
padding: 5px; | ||
display: flex; | ||
gap: 12px; | ||
} | ||
&__link { | ||
display: flex; | ||
flex-grow: 1; | ||
align-items: center; | ||
gap: 12px; | ||
padding: 6px 12px; | ||
font-weight: bold; | ||
} | ||
.related-team-provider { | ||
padding: 6px 12px; | ||
h6 { | ||
font-weight: bold; | ||
margin-bottom: 3px; | ||
} | ||
&__link { | ||
display: flex; | ||
gap: 12px; | ||
padding: 6px 12px; | ||
font-weight: bold; | ||
} | ||
} | ||
.related-team-resource { | ||
&__link { | ||
display: flex; | ||
gap: 12px; | ||
height: 44px; | ||
align-items: center; | ||
border-radius: var(--border-radius-large); | ||
&:hover { | ||
background-color: var(--color-background-hover); | ||
} | ||
&:focus { | ||
background-color: var(--color-background-hover); | ||
outline: 2px solid var(--color-primary-element); | ||
} | ||
} | ||
.resource__icon { | ||
width: 44px; | ||
height: 44px; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
text-align: center; | ||
} | ||
} | ||
} | ||
</style> |