[TaylorJ] Blogs

[TaylorJ] Blogs 1.3.0

No permission to download
Idea: make a competitor to XenPorta.
This is like a blog, but for the site, not the members.
Maybe the work done for Blogs can be repurposed into a Site Blog that is located on the [Home] tab.

[TaylorJ] Blogs 1.0.0 Beta 4 - seems like a better version of the seldomly used "Profile Posting". Is it possible to "disable" profile posting and encourage people to use [TJ] Blogs
 
I receive this server error periodically without doing anything:
One per hour to the minute, probably related to a cron entry

Code:
XF\Db\Exception: MySQL statement prepare error [1054]: Unknown column 't.view_count' in 'field list' src\XF\Db\AbstractStatement.php:230

            UPDATE xf_taylorj_blogs_blog_post AS t
            INNER JOIN xf_taylorj_blogs_blog_post_view AS tv ON (t.blog_post_id = tv.blog_post_id)
            SET t.view_count = t.view_count + tv.total
        
------------

#0 src\XF\Db\Mysqli\Statement.php(207): XF\Db\AbstractStatement->getException('MySQL statement...', 1054, '42S22')
#1 src\XF\Db\Mysqli\Statement.php(46): XF\Db\Mysqli\Statement->getException('MySQL statement...', 1054, '42S22')
#2 src\XF\Db\Mysqli\Statement.php(61): XF\Db\Mysqli\Statement->prepare()
#3 src\XF\Db\AbstractAdapter.php(96): XF\Db\Mysqli\Statement->execute()
#4 src\addons\TaylorJ\Blogs\Repository\BlogPost.php(25): XF\Db\AbstractAdapter->query('
            UPDATE xf_t...')
#5 src\addons\TaylorJ\Blogs\Cron\BlogPost.php(13): TaylorJ\Blogs\Repository\BlogPost->batchUpdateThreadViews()
#6 src\XF\Job\Cron.php(42): TaylorJ\Blogs\Cron\BlogPost::runViewUPdate(Object(XF\Entity\CronEntry))
#7 src\XF\Job\Manager.php(275): XF\Job\Cron->run(8)
#8 src\XF\Job\Manager.php(205): XF\Job\Manager->runJobInternal(Array, 8)
#9 src\XF\Job\Manager.php(89): XF\Job\Manager->runJobEntry(Array, 8)
#10 job.php(46): XF\Job\Manager->runQueue(false, 8)
#11 {main}

array(4) {
  ["url"] => string(18) "/xenforo23/job.php"
  ["referrer"] => string(36) "http://localhost/xenforo23/admin.php"
  ["_GET"] => array(0) {
  }
  ["_POST"] => array(0) {
  }
}
 
Works fine now... if you add a ; at the end of the line code you provided ;)

Phrase:
View attachment 308355

A little thing: in general and by convention the permissions of third-party add-ons appear at the end of the list on the permissions page, there they appear at the top of the list.
This has been fixed! Forgot to change a few phrase names after renaming the addon halfway through the first betas development.
Edit: Forgot to mention I agree on the positioning of the permissions, I had them at the top for convivence sake for myself but will have that changed in the next update as well!
XF2.3

Header image is distorted

View attachment 308356


Style variation is not applied here

View attachment 308357

And it would also be more conventional if the answer values of Created by (Author maybe?), Created on (Creation date maybe?) and Total posts were displayed aligned to the right, like resource infos. (It's a very small detail but the titles mentioned above should be dimmed in color).

View attachment 308358

Perhaps you should also use a name specific to blogs for the "Posts", in general we speak of "Blog entry" or perhaps even "Blog article", it would be less confusing with the "Posts" which correspond more to thread replies. This is manageable by everyone with the phrases but I specify it for all purposes.
Everything here has been fixed, thanks to you graciously, besides the header_image distortion. I haven't figured out a proper way to stretch the images perfectly due to not having any limitations (size and width/height) on the xf:uploadrow being used for it and not figuring out yet how to implement them.
XF 2.3

If you try to edit a blog, the new values are not applied to the blog, it creates a new blog with the new values.
Here, i just changed the header image...

View attachment 308361
This has been fixed! Had an improper param being looked for on editing.
Miss this one, taylorj_blogs_blog_post_view.less
Less:
.taylorJUserBlogs-post-content {
    padding: @xf-paddingLarge;
}
Added!
Idea: achieve a stable version before imagining anything else.
Agreed, not thinking of any other ideas at all right now.
 
Last edited:
I receive this server error periodically without doing anything:
One per hour to the minute, probably related to a cron entry

Code:
XF\Db\Exception: MySQL statement prepare error [1054]: Unknown column 't.view_count' in 'field list' src\XF\Db\AbstractStatement.php:230

            UPDATE xf_taylorj_blogs_blog_post AS t
            INNER JOIN xf_taylorj_blogs_blog_post_view AS tv ON (t.blog_post_id = tv.blog_post_id)
            SET t.view_count = t.view_count + tv.total
      
------------

#0 src\XF\Db\Mysqli\Statement.php(207): XF\Db\AbstractStatement->getException('MySQL statement...', 1054, '42S22')
#1 src\XF\Db\Mysqli\Statement.php(46): XF\Db\Mysqli\Statement->getException('MySQL statement...', 1054, '42S22')
#2 src\XF\Db\Mysqli\Statement.php(61): XF\Db\Mysqli\Statement->prepare()
#3 src\XF\Db\AbstractAdapter.php(96): XF\Db\Mysqli\Statement->execute()
#4 src\addons\TaylorJ\Blogs\Repository\BlogPost.php(25): XF\Db\AbstractAdapter->query('
            UPDATE xf_t...')
#5 src\addons\TaylorJ\Blogs\Cron\BlogPost.php(13): TaylorJ\Blogs\Repository\BlogPost->batchUpdateThreadViews()
#6 src\XF\Job\Cron.php(42): TaylorJ\Blogs\Cron\BlogPost::runViewUPdate(Object(XF\Entity\CronEntry))
#7 src\XF\Job\Manager.php(275): XF\Job\Cron->run(8)
#8 src\XF\Job\Manager.php(205): XF\Job\Manager->runJobInternal(Array, 8)
#9 src\XF\Job\Manager.php(89): XF\Job\Manager->runJobEntry(Array, 8)
#10 job.php(46): XF\Job\Manager->runQueue(false, 8)
#11 {main}

array(4) {
  ["url"] => string(18) "/xenforo23/job.php"
  ["referrer"] => string(36) "http://localhost/xenforo23/admin.php"
  ["_GET"] => array(0) {
  }
  ["_POST"] => array(0) {
  }
}
I'm unsure why but I think on your install it skipped creating the last table, view_count in this case, on installStep2. On another new fresh install as of 2 minutes ago it installed it for me locally so really not sure why it skipped for you.

If you have this on a test install would you mind attempting a reinstall of the addon to see if it misses that column again for you?
 
[TaylorJ] Blogs 1.0.0 Beta 4 - seems like a better version of the seldomly used "Profile Posting". Is it possible to "disable" profile posting and encourage people to use [TJ] Blogs
I would probably leave this up to forum owners to decide if they'd like to keep both / blogs over profile posts, don't want to enforce my ideals too much onto the end users.
 
For this one, would you mind grabbing a screenshot of your database, specifically the entirety of the xf_taylorj_blogs_blog_post table and posting it here. I was not able to reproduce this one on a fresh 2.3.2 install.
In src/addons/TaylorJ/Blogs/Setup.php replace both lines 48 and 72 with the below
I miss the line 72, now it works well. (y)
 
For info, i'm able to like my own blog entry.
And the reaction bar is displayed to the left corner instead the right corner, but it's detail.

1723223300652.webp
 
XF 2.3

Attachment are not visible in blog view, but maybe it's as designed?

1723223593977.webp

And it's a link in post view

1723223632749.webp
 
I think you're pretty busy with the PHP back-end, so if you don't mind I'll make suggestions for the HTML and Less front-end.
For the template taylorj_blogs_blog_view it would be wise to use the “cell” message structure, this allows for XF consistency.

Capture d'écran 2024-08-09 191014.webp

1723232603332.webp

HTML:
<xf:css src="taylorj_blogs_blog_view.less" />

<xf:breadcrumb source="$blog.getBreadcrumbs(true)" />

<xf:title>{$blog.blog_title}</xf:title>
<xf:description>{$blog.blog_description}</xf:description>

<div class="taylorjUserBlogs-blog-description">
<xf:pageaction>
    <xf:button href="{{ link('blogs/blog/add-post', $blog) }}" fa="fa-plus-square" class="button--cta">
        Create a new post
    </xf:button>
</xf:pageaction>

<xf:if contentcheck="true">
    <div class="u-pullRight buttonGroup-buttonWrapper">
        <xf:button class="button--link menuTrigger" data-xf-click="menu" aria-expanded="false" aria-haspopup="true"
            title="{{ phrase('more_options') }}">&#8226;&#8226;&#8226;</xf:button>
        <div class="menu" data-menu="menu" aria-hidden="true">
            <div class="menu-content">
                <h4 class="menu-header">{{ phrase('more_options') }}</h4>
                <xf:contentcheck>
                    <!--[XF:thread_tools_menu:top]-->
                    <xf:if is="$blog.canEdit()">
                        <a href="{{ link('blogs/blog/edit', $blog) }}" class="menu-linkRow">{{
                            phrase('taylorj_blogs_blog_edit') }}</a>
                    </xf:if>
                    <xf:if is="$blog.canDelete()">
                        <a href="{{ link('blogs/blog/delete', $blog) }}" data-xf-click="overlay" class="menu-linkRow">{{
                            phrase('taylorj_blogs_blog_delete') }}</a>
                    </xf:if>
                    <!--[XF:thread_tools_menu:bottom]-->
                </xf:contentcheck>
            </div>
        </div>
    </div>
</xf:if>
</div>

<xf:css src="message.less" />

<div class="block taylorjUserBlogs-block">
    <div class="taylorjUserBlogs-blog-posts">
        <xf:foreach loop="{$blogPosts}" key="$blog_post_id" value="$blogPost">
        <div class="block-container">
            <a href="{{ link('blogs/post', $blogPost) }}">
                <h2 class="block-header">{$blogPost.blog_post_title}</h2>
            </a>
            <div class="message">
                <div class="message-inner">
                    <div class="message-cell message-cell--main">
                        <div class="message-attribution">
                            <xf:date time="$blogPost.blog_post_date" />
                            <div class="u-pullRight">
                                {{ phrase('views') }}: {$blogPost.view_count}
                            </div>
                        </div>
                        <div class="message-content">
                            <div class="message-body">
                                {{ snippet($blogPost.blog_post_content, 750, {
                                    'stripQuote': true,
                                    'bbWrapper': true
                                }) }}
                            </div>
                        </div>
                        <xf:if is="$blogPost.blog_post_last_edit_date">
                            <div class="message-lastEdit">
                                {{ phrase('last_edited:') }} <xf:date time="$blogPost.blog_post_last_edit_date" />
                            </div>
                        </xf:if>
                    </div>
                </div>
            </div>
        </div>
        </xf:foreach>
        <xf:pagenav page="{$page}" perpage="{$perPage}" total="{$total}"
            link="blogs/blog/" data="{$blogPost}" wrapperclass="block-outer block-outer--after" />
    </div>
  
    <div class="taylorjUserBlogs-blog-details">
        <div class="taylorjBlogs-blog-header-image">
            <img src="{$blog.blog_header_image}" alt="Header Image" />
        </div>
        <div class="taylorJUserBlogs-details-text">
            <dl class="pairs pairs--justified">
                <dt>{{ phrase('author') }}</dt>
                <dd>{$blog.User.username}</dd>
            </dl>
            <dl class="pairs pairs--justified">
                <dt>{{ phrase('created') }}</dt>
                <dd><xf:date time="$blog.blog_creation_date" /></dd>
            </dl>
            <dl class="pairs pairs--justified">
                <dt>Entries</dt>
                <dd>{$blogPost.Blog.blog_post_count|number}</dd>
            </dl>
        </div>
    </div>
  
</div>

I used the XF syntax too for the blog description as you can see:
<xf:description>{$blog.blog_description}</xf:description>

This involves a small change in taylorj_blogs_blog_view.less:
Less:
.taylorjUserBlogs-blog-description {
    padding-bottom: 40px;
    //color: @xf-textColorDimmed;
}

I enjoy playing with the code a bit, you do what you want with my suggestions, they can be thrown in the trash, no offense here.
 
Last edited by a moderator:
For info, i'm able to like my own blog entry.
And the reaction bar is displayed to the left corner instead the right corner, but it's detail.

View attachment 308446
Styling is currently in the works for reacts to make them fit better (like regular articles) and also working on not allowing to react to own blog posts.

XF 2.3

Attachment are not visible in blog view, but maybe it's as designed?

View attachment 308447

And it's a link in post view

View attachment 308448
For the blog view the no attachments on the blog posts list is intentional for now, I could probably be persuaded to change it to show them as I was pretty 50/50 on to or to not.

Hmmm I thought I had thumbnails working, I'll take a look now.
I think you're pretty busy with the PHP back-end, so if you don't mind I'll make suggestions for the HTML and Less front-end.
For the template taylorj_blogs_blog_view it would be wise to use the “cell” message structure, this allows for XF consistency.

View attachment 308462

View attachment 308464

HTML:
<xf:css src="taylorj_blogs_blog_view.less" />

<xf:breadcrumb source="$blog.getBreadcrumbs(true)" />

<xf:title>{$blog.blog_title}</xf:title>
<xf:description>{$blog.blog_description}</xf:description>

<div class="taylorjUserBlogs-blog-description">
<xf:pageaction>
    <xf:button href="{{ link('blogs/blog/add-post', $blog) }}" fa="fa-plus-square" class="button--cta">
        Create a new post
    </xf:button>
</xf:pageaction>

<xf:if contentcheck="true">
    <div class="u-pullRight buttonGroup-buttonWrapper">
        <xf:button class="button--link menuTrigger" data-xf-click="menu" aria-expanded="false" aria-haspopup="true"
            title="{{ phrase('more_options') }}">&#8226;&#8226;&#8226;</xf:button>
        <div class="menu" data-menu="menu" aria-hidden="true">
            <div class="menu-content">
                <h4 class="menu-header">{{ phrase('more_options') }}</h4>
                <xf:contentcheck>
                    <!--[XF:thread_tools_menu:top]-->
                    <xf:if is="$blog.canEdit()">
                        <a href="{{ link('blogs/blog/edit', $blog) }}" class="menu-linkRow">{{
                            phrase('taylorj_blogs_blog_edit') }}</a>
                    </xf:if>
                    <xf:if is="$blog.canDelete()">
                        <a href="{{ link('blogs/blog/delete', $blog) }}" data-xf-click="overlay" class="menu-linkRow">{{
                            phrase('taylorj_blogs_blog_delete') }}</a>
                    </xf:if>
                    <!--[XF:thread_tools_menu:bottom]-->
                </xf:contentcheck>
            </div>
        </div>
    </div>
</xf:if>
</div>

<xf:css src="message.less" />

<div class="block taylorjUserBlogs-block">
    <div class="taylorjUserBlogs-blog-posts">
        <xf:foreach loop="{$blogPosts}" key="$blog_post_id" value="$blogPost">
        <div class="block-container">
            <a href="{{ link('blogs/post', $blogPost) }}">
                <h2 class="block-header">{$blogPost.blog_post_title}</h2>
            </a>
            <div class="message">
                <div class="message-inner">
                    <div class="message-cell message-cell--main">
                        <div class="message-attribution">
                            <xf:date time="$blogPost.blog_post_date" />
                            <div class="u-pullRight">
                                {{ phrase('views') }}: {$blogPost.view_count}
                            </div>
                        </div>
                        <div class="message-content">
                            <div class="message-body">
                                {{ snippet($blogPost.blog_post_content, 750, {
                                    'stripQuote': true,
                                    'bbWrapper': true
                                }) }}
                            </div>
                        </div>
                        <xf:if is="$blogPost.blog_post_last_edit_date">
                            <div class="message-lastEdit">
                                {{ phrase('last_edited:') }} <xf:date time="$blogPost.blog_post_last_edit_date" />
                            </div>
                        </xf:if>
                    </div>
                </div>
            </div>
        </div>
        </xf:foreach>
        <xf:pagenav page="{$page}" perpage="{$perPage}" total="{$total}"
            link="blogs/blog/" data="{$blogPost}" wrapperclass="block-outer block-outer--after" />
    </div>
 
    <div class="taylorjUserBlogs-blog-details">
        <div class="taylorjBlogs-blog-header-image">
            <img src="{$blog.blog_header_image}" alt="Header Image" />
        </div>
        <div class="taylorJUserBlogs-details-text">
            <dl class="pairs pairs--justified">
                <dt>{{ phrase('author') }}</dt>
                <dd>{$blog.User.username}</dd>
            </dl>
            <dl class="pairs pairs--justified">
                <dt>{{ phrase('created') }}</dt>
                <dd><xf:date time="$blog.blog_creation_date" /></dd>
            </dl>
            <dl class="pairs pairs--justified">
                <dt>Entries</dt>
                <dd>{$blogPost.Blog.blog_post_count|number}</dd>
            </dl>
        </div>
    </div>
 
</div>

I used the XF syntax too for the blog description as you can see:
<xf:description>{$blog.blog_description}</xf:description>

This involves a small change in taylorj_blogs_blog_view.less:
Less:
.taylorjUserBlogs-blog-description {
    padding-bottom: 40px;
    //color: @xf-textColorDimmed;
}

I enjoy playing with the code a bit, you do what you want with my suggestions, they can be thrown in the trash, no offense here.
Implemented thank you!
 
I just tried minorHeader instead Header for blog posts, that's not bad, maybe something you can think about.
The render is lighter, cleaner, imho.

1723241680527.webp

XF 2.3

I tried to post emoji and code and they are not rendered in blog view.
 
I just tried minorHeader instead Header for blog posts, that's not bad, maybe something you can think about.
The render is lighter, cleaner, imho.

View attachment 308473

XF 2.3

I tried to post emoji and code and they are not rendered in blog view.
Oh that does look nice, I'll give it a better look now.

Also strange update on the thumbnails and emoji/code bbcode not showing up. They are for me and I can't tell why...

1723242037875.webp

Edit: OHHHH you said blog view for emoji and code, that's probably due to the snippet I'll check.
 
Also strange update on the thumbnails and emoji/code bbcode not showing up. They are for me and I can't tell why...
Blog post view, yes, bbcode and emoji are showing well, but not thumbnail on my side. I will look into it more precisely.
1723242408208.webp

But bbcode and emoji are not rendered in blog view
 
Styling is currently in the works for reacts to make them fit better (like regular articles) and also working on not allowing to react to own blog posts.
You can use the same structure i used for blog_view template
HTML:
<xf:css src="taylorj_blogs_blog_post_view.less" />
<xf:css src="message.less" />

<xf:breadcrumb source="$blogPost.getBreadcrumbs(true)" />

<xf:title>{$blogPost.blog_post_title}</xf:title>

<xf:description meta="false">
    <div class="u-pullLeft">
        <ul class="listInline listInline--bullet">
            <li>
                <xf:fa icon="fa-user" title="{{ phrase('thread_starter')|for_attr }}" />
                <span class="u-srOnly">{{ phrase('thread_starter') }}</span>

                <xf:username user="{$blogPost.User}" class="u-concealed" />
            </li>
            <li>
                <xf:fa icon="fa-clock" title="{{ phrase('start_date')|for_attr }}" />
                <span class="u-srOnly">{{ phrase('start_date') }}</span>

                <a href="{{ link('blogs/post', $blogPost) }}" class="u-concealed">
                    <xf:date time="{$blogPost.blog_post_date}" />
                </a>
            </li>
        </ul>
    </div>
    <xf:if contentcheck="true">
        <div class="u-pullRight buttonGroup-buttonWrapper">
            <xf:button class="button--link menuTrigger" data-xf-click="menu" aria-expanded="false" aria-haspopup="true"
                title="{{ phrase('more_options') }}">&#8226;&#8226;&#8226;</xf:button>
            <div class="menu" data-menu="menu" aria-hidden="true">
                <div class="menu-content">
                    <h4 class="menu-header">{{ phrase('more_options') }}</h4>
                    <xf:contentcheck>
                        <!--[XF:thread_tools_menu:top]-->
                        <xf:if is="$blogPost.canEdit()">
                            <a href="{{ link('blogs/post/edit', $blogPost) }}" class="menu-linkRow">{{
                                phrase('taylorj_blogs_blog_post_edit') }}</a>
                        </xf:if>
                        <xf:if is="$blogPost.canDelete()">
                            <a href="{{ link('blogs/post/delete', $blogPost) }}" data-xf-click="overlay"
                                class="menu-linkRow">{{
                                phrase('taylorj_blogs_blog_post_delete') }}</a>
                        </xf:if>
                        <!--[XF:thread_tools_menu:bottom]-->
                    </xf:contentcheck>
                </div>
            </div>
        </div>
    </xf:if>
</xf:description>


<div class="block">
    <div class="block-container">
        <div class="message">
                <div class="message-inner">
                    <div class="message-cell message-cell--main">
                        <div class="message-attribution">
                            <xf:date time="$blogPost.blog_post_date" />
                            <div class="u-pullRight">
                                {{ phrase('views') }}: {$blogPost.view_count}
                            </div>
                        </div>
                        <div class="message-content">
                            <div class="message-body">
                                {{ bb_code($blogPost.blog_post_content, 'blog_post_id', $blogPost) }}
                            </div>
                            <xf:react content="{$blogPost}" link="blogs/post/react" list="< .taylorJUserBlogs-post-content | .js-reactionList" />
                            <div class="reactionsBar js-reactionList {{ $blogPost.reactions ? 'is-active' : ''}}">
                                <xf:if is="$blogPost.reactions">
                                    <xf:reactions content="{$blogPost}" link="blogs/post/reactions" />
                                </xf:if>
                            </div>
                        </div>
                    </div>
            </div>
        </div>
        <aside class="message-articleUserInfo">
            <div class="message-cell">
                <div class="contentRow">
                    <div class="contentRow-figure">
                        <xf:avatar user="$blogPost.User" size="m" />
                    </div>
                    <div class="contentRow-main">

                        <div class="message-articleUserFirstLine">
                            <div class="message-articleWrittenBy u-srOnly">{{ phrase('article_written_by') }}</div>
                            <h3 class="message-articleUserName">
                                <xf:username user="$blogPost.User" rich="true" />
                            </h3>

                            <xf:if contentcheck="true">
                                <div class="message-articleUserBlurb">
                                    <xf:contentcheck>
                                        <xf:userblurb user="$blogPost.User" tag="div" />
                                    </xf:contentcheck>
                                </div>
                            </xf:if>
                        </div>

                        <xf:if contentcheck="true">
                            <div class="message-articleUserAbout">
                                <xf:contentcheck>
                                    <xf:if is="$blogPost.User.Profile.about != ''">
                                        {{ bb_code($blogPost.User.Profile.about, 'user:about', $blogPost.User) }}
                                    </xf:if>
                                </xf:contentcheck>
                            </div>
                        </xf:if>

                        <xf:if contentcheck="true">
                            <div class="message-articleUserBanners">
                                <xf:contentcheck>
                                    <xf:userbanners user="$user" />
                                </xf:contentcheck>
                            </div>
                        </xf:if>

                        <div class="message-articleUserStats">
                            <ul class="listInline listInline--bullet">
                                <!--[XF:stats:start]-->
                                <li>
                                    <dl class="pairs pairs--inline">
                                        <dt>{{ phrase('taylorj_blogs_blogs_total') }}</dt>
                                        <dd>{$blogPost.User.taylorj_blogs_blog_count|number}</dd>
                                    </dl>
                                </li>
                                <!--[XF:stats:after_messages]-->
                                <li>
                                    <dl class="pairs pairs--inline">
                                        <dt>{{ phrase('reaction_score') }}</dt>
                                        <dd>{$blogPost.User.reaction_score|number}</dd>
                                    </dl>
                                </li>
                                <!--[XF:stats:after_likes]-->
                                <!--[XF:stats:after_reactions]-->
                                <xf:if is="$xf.options.enableTrophies">
                                    <li>
                                        <dl class="pairs pairs--inline">
                                            <dt>{{ phrase('points') }}</dt>
                                            <dd>{$blogPost.User.trophy_points|number}</dd>
                                        </dl>
                                    </li>
                                </xf:if>
                                <!--[XF:stats:end]-->
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </aside>
    </div>
</div>

1723243226950.webp
 
XF 2.3

Each time I edit a blog post it increases the number of posts.
I just have 3 posts/entries

Capture d'écran 2024-08-09 224359.webp
 
Last edited by a moderator:
Back
Top Bottom