Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion com.woltlab.wcf/templates/articleList.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

{include file='header'}

<div class="section">
<div class="section entryCardList__container">
{unsafe:$listView->render()}
</div>

Expand Down
132 changes: 68 additions & 64 deletions com.woltlab.wcf/templates/articleListItems.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

{foreach from=$view->getItems() item='article' name='articles'}
{if $article->getArticleContent()}
<article class="contentItem contentItemMultiColumn listView__item" data-object-id="{$article->getObjectID()}">
<div class="contentItemOptions">
<article class="entryCardList__item listView__item" data-object-id="{$article->getObjectID()}">
<div class="entryCardList__item__buttons">
{if $view->hasBulkInteractions()}
<label class="button small jsTooltip" title="{lang}wcf.clipboard.item.mark{/lang}">
<input type="checkbox" class="listView__selectItem" aria-label="{lang}wcf.clipboard.item.mark{/lang}">
Expand All @@ -12,77 +12,81 @@

{unsafe:$view->renderInteractionContextMenuButton($article)}
</div>

<div class="contentItemLink">
<div class="contentItemImage contentItemImageLarge">
<img
class="contentItemImageElement"
src="{if $article->getTeaserImage()}{$article->getTeaserImage()->getThumbnailLink('medium')}{else}{$__wcf->getStyleHandler()->getStyle()->getCoverPhotoURL()}{/if}"
height="{if $article->getTeaserImage()}{@$article->getTeaserImage()->getThumbnailHeight('medium')}{else}{@$__wcf->getStyleHandler()->getStyle()->getCoverPhotoHeight()}{/if}"
width="{if $article->getTeaserImage()}{@$article->getTeaserImage()->getThumbnailWidth('medium')}{else}{@$__wcf->getStyleHandler()->getStyle()->getCoverPhotoWidth()}{/if}"
loading="lazy"
alt="">

{hascontent}
<div class="contentItemBadges">
{content}
{if $article->isDeleted}<span class="badge label red contentItemBadge contentItemBadgeIsDeleted">{lang}wcf.message.status.deleted{/lang}</span>{/if}
{if !$article->isPublished()}<span class="badge label green contentItemBadge contentItemBadgeIsDisabled">{lang}wcf.message.status.disabled{/lang}</span>{/if}
{if $article->isNew()}<span class="badge label contentItemBadge contentItemBadgeNew">{lang}wcf.message.new{/lang}</span>{/if}

{event name='contentItemBadges'}
{/content}
</div>
{/hascontent}
</div>

<div class="contentItemContent">
{if $article->hasLabels()}
<div class="contentItemLabels">
{foreach from=$article->getLabels() item=label}
{@$label->render('contentItemLabel')}
{/foreach}
</div>
{/if}

<h2 class="contentItemTitle"><a href="{$article->getLink()}" class="contentItemTitleLink">{$article->getTitle()}</a></h2>

<div class="contentItemDescription">
{@$article->getFormattedTeaser()}

<div class="entryCardList__item__image">
<img
class="entryCardList__item__image__element"
src="{if $article->getTeaserImage()}{$article->getTeaserImage()->getThumbnailLink('medium')}{else}{$__wcf->getStyleHandler()->getStyle()->getCoverPhotoURL()}{/if}"
height="{if $article->getTeaserImage()}{$article->getTeaserImage()->getThumbnailHeight('medium')}{else}{$__wcf->getStyleHandler()->getStyle()->getCoverPhotoHeight()}{/if}"
width="{if $article->getTeaserImage()}{$article->getTeaserImage()->getThumbnailWidth('medium')}{else}{$__wcf->getStyleHandler()->getStyle()->getCoverPhotoWidth()}{/if}"
Comment thread
BurntimeX marked this conversation as resolved.
loading="lazy"
alt=""
>

{hascontent}
<div class="entryCardList__item__badges">
{content}
{if $article->isDeleted}<span class="badge red">{lang}wcf.message.status.deleted{/lang}</span>{/if}
{if !$article->isPublished()}<span class="badge green">{lang}wcf.message.status.disabled{/lang}</span>{/if}
{if $article->isNew()}<span class="badge">{lang}wcf.message.new{/lang}</span>{/if}

{event name='contentItemBadges'}{* deprecated: use badges instead *}
{event name='badges'}
{/content}
</div>
{/hascontent}
</div>

<div class="entryCardList__item__content">
{if $article->hasLabels()}
<ul class="entryCardList__item__labels labelList">
{foreach from=$article->getLabels() item=label}
<li>{unsafe:$label->render()}</li>
{/foreach}
</ul>
{/if}

<h2 class="entryCardList__item__title">
<a href="{$article->getLink()}" class="entryCardList__item__link">{$article->getTitle()}</a>
</h2>

<div class="entryCardList__item__teaser">
{unsafe:$article->getFormattedTeaser()}
</div>
</div>
<div class="contentItemMeta">
<span class="contentItemMetaImage">
{@$article->getUserProfile()->getAvatar()->getImageTag(32)}
</span>

<div class="entryCardList__item__meta">
<div class="entryCardList__item__meta__image">
{unsafe:$article->getUserProfile()->getAvatar()->getImageTag(32)}
</div>

<div class="contentItemMetaContent">
<div class="contentItemMetaAuthor">
{@$article->getUserProfile()->getFormattedUsername()}
<div class="entryCardList__item__meta__content">
<div class="entryCardList__item__meta__author">
{unsafe:$article->getUserProfile()->getFormattedUsername()}
</div>
<div class="contentItemMetaTime">
{@$article->time|time}

<div class="entryCardList__item__meta__time">
{time time=$article->time}
</div>
</div>
<div class="contentItemMetaIcons">

<div class="entryCardList__item__meta__icons">
{if MODULE_LIKE && $__wcf->getSession()->getPermission('user.like.canViewLike') && $article->cumulativeLikes}
<div class="contentItemMetaIcon">
<div class="entryCardList__item__meta__icon">
{include file='shared_topReaction' cachedReactions=$article->cachedReactions render='short'}
</div>
{/if}
{if $article->getDiscussionProvider()->getDiscussionCountPhrase()}{* empty phrase indicates that comments are disabled *}
<div class="contentItemMetaIcon">
<div class="entryCardList__item__meta__icon">
{icon name='comments'}
<span aria-label="{$article->getDiscussionProvider()->getDiscussionCountPhrase()}">
{$article->getDiscussionProvider()->getDiscussionCount()}
</span>
</div>
{/if}

{event name='contentItemMetaIcons'}
{event name='contentItemMetaIcons'}{* deprecated: use badges instead *}
{event name='metaIcons'}
</div>
</div>
</article>
Expand All @@ -91,38 +95,38 @@
{if MODULE_WCF_AD && !$disableAds}
{if $tpl[foreach][articles][iteration] === 1}
{hascontent}
<div class="contentItem contentItemAd">
{content}{@$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.after1stArticle')}{/content}
<div class="entryCardList__item entryCardList__item--ad">
{content}{unsafe:$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.after1stArticle')}{/content}
</div>
{/hascontent}
{else}
{if $tpl[foreach][articles][iteration] % 2 === 0}
{hascontent}
<div class="contentItem contentItemAd">
{content}{@$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery2ndArticle')}{/content}
<div class="entryCardList__item entryCardList__item--ad">
{content}{unsafe:$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery2ndArticle')}{/content}
</div>
{/hascontent}
{/if}

{if $tpl[foreach][articles][iteration] % 3 === 0}
{hascontent}
<div class="contentItem contentItemAd">
{content}{@$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery3rdArticle')}{/content}
<div class="entryCardList__item entryCardList__item--ad">
{content}{unsafe:$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery3rdArticle')}{/content}
</div>
{/hascontent}
{/if}

{if $tpl[foreach][articles][iteration] % 5 === 0}
{hascontent}
<div class="contentItem contentItemAd">
{content}{@$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery5thArticle')}{/content}
<div class="entryCardList__item entryCardList__item--ad">
{content}{unsafe:$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery5thArticle')}{/content}
</div>
{/hascontent}

{if $tpl[foreach][articles][iteration] % 10 === 0}
{hascontent}
<div class="contentItem contentItemAd">
{content}{@$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery10thArticle')}{/content}
<div class="entryCardList__item entryCardList__item--ad">
{content}{unsafe:$__wcf->getAdHandler()->getAds('com.woltlab.wcf.article.afterEvery10thArticle')}{/content}
</div>
{/hascontent}
{/if}
Expand Down
4 changes: 2 additions & 2 deletions com.woltlab.wcf/templates/shared_listView.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@
</div>
</div>

<div class="listView__footer">
<div class="listView__footer" id="{$view->getID()}_footer">
{if $view->hasBulkInteractions()}
<div id="{$view->getID()}_selectionBar" class="listView__selectionBar dropdown" hidden>
<button type="button" id="{$view->getID()}_bulkInteractionButton" class="button listView__bulkInteractionButton dropdownToggle"></button>
<button type="button" id="{$view->getID()}_bulkInteractionButton" class="button small listView__bulkInteractionButton dropdownToggle"></button>
<ul class="dropdownMenu">
<li class="disabled"><span>{lang}wcf.global.loading{/lang}</span></li>
<li class="dropdownDivider"></li>
Expand Down
3 changes: 3 additions & 0 deletions ts/WoltLabSuite/Core/Component/ListView/Selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ export class Selection extends EventTarget {
return;
}

this.dispatchEvent(new CustomEvent("list-view:update-selection"));

if (selectedIds.length === 0) {
this.#selectionBar.hidden = true;
return;
Expand Down Expand Up @@ -284,6 +286,7 @@ export class Selection extends EventTarget {

interface SelectionEventMap {
"list-view:get-bulk-interactions": CustomEvent<{ objectIds: number[] }>;
"list-view:update-selection": CustomEvent<void>;
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
Expand Down
13 changes: 13 additions & 0 deletions ts/WoltLabSuite/Core/Component/ListView/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class State extends EventTarget {
readonly #pagination: WoltlabCorePaginationElement;
readonly #selection: Selection;
readonly #sorting: Sorting;
readonly #listViewFooter: HTMLElement;
#pageNo: number;

constructor(
Expand All @@ -39,6 +40,8 @@ export class State extends EventTarget {
this.#baseUrl = baseUrl;
this.#pageNo = pageNo;

this.#listViewFooter = document.getElementById(`${viewId}_footer`) as HTMLElement;

this.#pagination = document.getElementById(`${viewId}_pagination`) as WoltlabCorePaginationElement;
this.#pagination.addEventListener("switchPage", (event: CustomEvent) => {
void this.#switchPage(event.detail, StateChangeCause.Pagination);
Expand All @@ -60,12 +63,16 @@ export class State extends EventTarget {
new CustomEvent("list-view:get-bulk-interactions", { detail: { objectIds: event.detail.objectIds } }),
);
});
this.#selection.addEventListener("list-view:update-selection", () => {
this.#updateListViewFooter();
});

window.addEventListener("popstate", () => {
this.#handlePopState();
});

this.#updatePaginationUrl();
this.#updateListViewFooter();
}

getPageNo(): number {
Expand Down Expand Up @@ -97,6 +104,8 @@ export class State extends EventTarget {
if (cause === StateChangeCause.Change || cause === StateChangeCause.Pagination) {
this.#updateQueryString();
}

this.#updateListViewFooter();
}

#switchPage(pageNo: number, source: StateChangeCause): void {
Expand Down Expand Up @@ -176,6 +185,10 @@ export class State extends EventTarget {
this.#switchPage(pageNo, StateChangeCause.History);
}

#updateListViewFooter(): void {
this.#listViewFooter.hidden = this.#pagination.count < 2 && this.#selection.getSelectedIds().length === 0;
}

setBulkInteractionContextMenuOptions(options: string): void {
this.#selection.setBulkInteractionContextMenuOptions(options);
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function __construct()
$this->setItemsPerPage(\ARTICLES_PER_PAGE);
$this->setSortField('time');
$this->setSortOrder(\ARTICLE_SORT_ORDER);
$this->setCssClassName('contentItemList');
$this->setCssClassName('entryCardList');
}

#[\Override]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ public function getListView(array $tagIDs): ArticleListView
{
return new TaggedArticleListView($tagIDs);
}

#[\Override]
public function getContainerCssClassName(): string
{
return 'entryCardList__container';
}
}
Loading