Skip to content

Commit

Permalink
feat(favorites): Implement frontend support for page favorites
Browse files Browse the repository at this point in the history
Fixes: #300

Signed-off-by: Jonas <jonas@freesources.org>
  • Loading branch information
mejo- committed Oct 28, 2024
1 parent e9f2948 commit 0882cb3
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 10 deletions.
26 changes: 26 additions & 0 deletions cypress/e2e/page-list.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,32 @@ describe('Page list', function() {
})
})

describe('Page favorites', function() {
it('Allows to add and remove pages from favorites', function() {
cy.get('.page-list .page-list-favorites')
.should('not.exist')

cy.openPageMenu('Day 1')
cy.clickMenuButton('Add to favorites')
cy.get('.page-list .page-list-favorites')
.should('contain', 'Day 1')

cy.get('.page-list-favorites-list')
.should('be.visible')
cy.get('.page-list-favorites .toggle-favorites-button')
.click()
cy.get('.page-list-favorites-list')
.should('not.be.visible')
cy.get('.page-list-favorites .toggle-favorites-button')
.click()

cy.openPageMenu('Day 1')
cy.clickMenuButton('Remove from favorites')
cy.get('.page-list .page-list-favorites')
.should('not.exist')
})
})

describe('Print view', function() {
it('renders all the pages', function() {
let printStub
Expand Down
19 changes: 16 additions & 3 deletions src/apis/collectives/userSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { collectivesUrl } from './urls.js'
/**
* Set the page order for the current user
*
* @param {number} collectiveId ID of the colletive to be updated
* @param {number} collectiveId ID of the collective to be updated
* @param {number} pageOrder the desired page order for the current user
*/
export function setCollectiveUserSettingPageOrder(collectiveId, pageOrder) {
Expand All @@ -20,9 +20,9 @@ export function setCollectiveUserSettingPageOrder(collectiveId, pageOrder) {
}

/**
* Set the the `show recent pages` toggle for the current user
* Set the `show recent pages` toggle for the current user
*
* @param {number} collectiveId ID of the colletive to be updated
* @param {number} collectiveId ID of the collective to be updated
* @param {boolean} showRecentPages the desired value
*/
export function setCollectiveUserSettingShowRecentPages(collectiveId, showRecentPages) {
Expand All @@ -31,3 +31,16 @@ export function setCollectiveUserSettingShowRecentPages(collectiveId, showRecent
{ showRecentPages },
)
}

/**
* Set favorite pages for the current user
*
* @param {number} collectiveId ID of the collective to be updated
* @param {Array} favoritePages the desired value
*/
export function setCollectiveUserSettingFavoritePages(collectiveId, favoritePages) {
return axios.put(
collectivesUrl(collectiveId, '_userSettings', 'favoritePages'),
{ favoritePages: JSON.stringify(favoritePages) },
)
}
29 changes: 28 additions & 1 deletion src/components/Page/PageActionMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@
{{ t('collectives', 'Show in Files') }}
</NcActionLink>

<!-- Favor page action: only displayed in page list and not for landing page -->
<NcActionButton v-if="inPageList"
:close-after-click="true"
@click="toggleFavoritePage({ id: currentCollective.id, pageId })">
<template #icon>
<StarOffIcon v-if="isFavoritePage(currentCollective.id, pageId)" :size="20" />
<StarIcon v-else :size="20" />
</template>
{{ toggleFavoriteString }}
</NcActionButton>

<!-- Share page action: only displayed in page list and not for landing page (already in collectives actions there) -->
<NcActionButton v-if="inPageList && currentCollectiveCanShare && !isLandingPage"
:close-after-click="true"
Expand Down Expand Up @@ -143,6 +154,8 @@ import MoveOrCopyModal from './MoveOrCopyModal.vue'
import PagesTemplateIcon from '../Icon/PagesTemplateIcon.vue'
import PageActionLastUser from './PageActionLastUser.vue'
import ShareVariantIcon from 'vue-material-design-icons/ShareVariant.vue'
import StarIcon from 'vue-material-design-icons/Star.vue'
import StarOffIcon from 'vue-material-design-icons/StarOff.vue'
import pageMixin from '../../mixins/pageMixin.js'
import { usePagesStore } from '../../stores/pages.js'

Expand All @@ -165,6 +178,8 @@ export default {
PagesTemplateIcon,
PageActionLastUser,
ShareVariantIcon,
StarIcon,
StarOffIcon,
},

mixins: [
Expand Down Expand Up @@ -228,6 +243,7 @@ export default {
'currentCollectiveCanEdit',
'currentCollectiveCanShare',
'currentCollectiveIsPageShare',
'isFavoritePage',
]),
...mapState(usePagesStore, [
'hasSubpages',
Expand Down Expand Up @@ -264,6 +280,12 @@ export default {
return generateUrl(`/f/${this.currentPage.id}`)
},

toggleFavoriteString() {
return this.isFavoritePage(this.currentCollective.id, this.pageId)
? t('collectives', 'Remove from favorites')
: t('collectives', 'Add to favorites')
},

editTemplateString() {
return this.hasTemplate
? t('collectives', 'Edit template for subpages')
Expand Down Expand Up @@ -310,7 +332,12 @@ export default {
'show',
'toggle',
]),
...mapActions(usePagesStore, ['setFullWidthView']),
...mapActions(useCollectivesStore, [
'toggleFavoritePage',
]),
...mapActions(usePagesStore, [
'setFullWidthView',
]),

onCheckFullWidthView() {
this.setFullWidthView({ pageId: this.currentPage.id, fullWidthView: true })
Expand Down
21 changes: 21 additions & 0 deletions src/components/PageList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<SkeletonLoading type="items" :count="3" />
</div>
<div v-else class="page-list">
<!-- Landing page -->
<Item key="Readme"
:to="currentCollectivePath"
:page-id="rootPage.id"
Expand All @@ -81,6 +82,8 @@
:filtered-view="false"
class="page-list-root-page"
@click.native="show('details')" />

<!-- Sort order container (optional) -->
<div v-if="!sortedBy('byOrder')" class="sort-order-container">
<span class="sort-order-chip">
{{ sortedBy('byTitle') ? t('collectives', 'Sorted by title') : t('collectives', 'Sorted by recently changed') }}
Expand All @@ -94,12 +97,19 @@
</NcButton>
</span>
</div>

<!-- Favorites -->
<PageFavorites v-if="showFavorites" />

<!-- Templates (optional) -->
<SubpageList v-if="templateView"
:key="templateView.id"
:page="templateView"
:level="1"
:filtered-view="isFilteredView"
:is-template="true" />

<!-- Filtered view page list -->
<div v-if="isFilteredView" ref="pageListFiltered" class="page-list-filtered">
<NcAppNavigationCaption v-if="filteredPages.length > 0" :name="t('Collectives','Results in title')" />
<RecycleScroller v-if="filteredPages.length > 0"
Expand Down Expand Up @@ -133,6 +143,8 @@
<SkeletonLoading type="items" :count="3" />
</div>
</div>

<!-- Unfiltered view page list -->
<Draggable v-else
:list="subpages"
:parent-id="rootPage.id"
Expand All @@ -146,6 +158,8 @@
class="page-list-drag-item" />
</Draggable>
</div>

<!-- Page trash -->
<PageTrash v-if="displayTrash" />
</NcAppContentList>
</template>
Expand All @@ -165,6 +179,7 @@ import CloseIcon from 'vue-material-design-icons/Close.vue'
import Draggable from './PageList/Draggable.vue'
import SubpageList from './PageList/SubpageList.vue'
import Item from './PageList/Item.vue'
import PageFavorites from './PageList/PageFavorites.vue'
import PageTrash from './PageList/PageTrash.vue'
import SortAlphabeticalAscendingIcon from 'vue-material-design-icons/SortAlphabeticalAscending.vue'
import SortAscendingIcon from 'vue-material-design-icons/SortAscending.vue'
Expand Down Expand Up @@ -193,6 +208,7 @@ export default {
Draggable,
Item,
PagesTemplateIcon,
PageFavorites,
PageTrash,
SubpageList,
SortAlphabeticalAscendingIcon,
Expand Down Expand Up @@ -229,6 +245,7 @@ export default {
'rootPage',
'templatePage',
'currentPage',
'hasFavoritePages',
'keptSortable',
'visibleSubpages',
'sortByOrder',
Expand Down Expand Up @@ -276,6 +293,10 @@ export default {
return (sortOrder) => this.sortByOrder === sortOrder
},

showFavorites() {
return !this.isFilteredView && this.hasFavoritePages
},

isFilteredView() {
return this.filterString !== ''
},
Expand Down
48 changes: 42 additions & 6 deletions src/components/PageList/Item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@
class="item-icon-badge"
:class="isCollapsed(pageId) ? 'collapsed' : 'expanded'" />
</template>
<template v-if="showFavoriteStar">
<StarIcon v-show="!filteredView"
:size="18"
fill-color="var(--color-warning)"
:title="t('collectives', 'Favorite')"
class="item-icon-favorite" />
</template>
</div>
<router-link :to="to"
draggable="false"
Expand Down Expand Up @@ -88,6 +95,7 @@
<script>
import { generateUrl } from '@nextcloud/router'
import { mapActions, mapState } from 'pinia'
import { useCollectivesStore } from '../../stores/collectives.js'
import { usePagesStore } from '../../stores/pages.js'
import { TEMPLATE_PAGE } from '../../constants.js'
import isMobile from '@nextcloud/vue/dist/Mixins/isMobile.js'
Expand All @@ -99,6 +107,7 @@ import pageMixin from '../../mixins/pageMixin.js'
import PageIcon from '../Icon/PageIcon.vue'
import PageActionMenu from '../Page/PageActionMenu.vue'
import PageTemplateIcon from '../Icon/PageTemplateIcon.vue'
import StarIcon from 'vue-material-design-icons/Star.vue'
import { scrollToPage } from '../../util/scrollToElement.js'

export default {
Expand All @@ -113,6 +122,7 @@ export default {
PageActionMenu,
PageTemplateIcon,
PlusIcon,
StarIcon,
},

mixins: [
Expand Down Expand Up @@ -165,6 +175,10 @@ export default {
type: Boolean,
default: false,
},
inFavoriteList: {
type: Boolean,
default: false,
},
hasVisibleSubpages: {
type: Boolean,
default: false,
Expand All @@ -191,6 +205,10 @@ export default {
},

computed: {
...mapState(useCollectivesStore, [
'currentCollective',
'isFavoritePage',
]),
...mapState(usePagesStore, [
'isCollapsed',
'currentPage',
Expand All @@ -208,14 +226,13 @@ export default {
&& this.currentPage.id === this.pageId
},

indent() {
// Start indention at level 2. And limit to 5 to prevent nasty subtrees
return Math.min(Math.max(0, this.level - 1), 4)
isCollapsible() {
// root page and favorites are not collapsible
return this.level > 0 && !this.inFavoriteList && this.hasVisibleSubpages
},

isCollapsible() {
// root page is not collapsible
return (this.level > 0 && this.hasVisibleSubpages)
showFavoriteStar() {
return !this.inFavoriteList && this.isFavoritePage(this.currentCollective.id, this.pageId)
},

pageTitleString() {
Expand Down Expand Up @@ -366,6 +383,10 @@ export default {
span.item-icon-badge {
background-color: var(--color-primary-element-light);
}

span.item-icon-favorite {
background-color: var(--color-primary-element-light);
}
}

&:hover, &:focus, &:active, &.highlight {
Expand All @@ -374,6 +395,10 @@ export default {
span.item-icon-badge {
background-color: var(--color-background-hover);
}

span.item-icon-favorite {
background-color: var(--color-background-hover);
}
}

&.highlight-animation {
Expand Down Expand Up @@ -442,6 +467,17 @@ export default {
transform: rotate(90deg);
}
}

// Configure favorite icon
.item-icon-favorite {
position: absolute;
top: 0;
right: -1px;
cursor: pointer;
border: 0;
border-radius: 50%;
background-color: var(--color-main-background);
}
}

.app-content-list-item-line-one {
Expand Down
Loading

0 comments on commit 0882cb3

Please sign in to comment.