Module

@softwarebrothers/admin-bro-blog

AdminBro feature allowing you to add an amazing blog to your project.

Features

  • Beautiful UI
  • Uploading inline files and splash screen
  • Auto-saving
  • Draft and Publish states
  • Assign Tags
  • Managing of post's Meta-Data like ogTags, Facebook meta or Twitter meta

Demo

To see the demo visit: http://premium.adminbro.com

Where to buy this addon?

The price of the addon is 100 USD. It covers:

  • addon itself with the license to host it on 1 site
  • access addon updates for 1 year
  • our support

To buy it - contact us on slack on #premium addons channel or the email: [email protected]

Installation

To install the addon run:

yarn add @softwarebrothers/admin-bro-blog

and install it's peer dependency @admin-bro/upload

yarn add @admin-bro/upload

Usage

As with other features - this one also has to be passed to the resource in AdminBroOptions#resources option:

import AdminBro from 'admin-bro'
import AdminBroExpress from '@admin-bro/express'
import blogFeature from '@softwarebrothers/admin-bro-blog'

// part where you load adapter and models
import BlogPost from './blog-post'

const options = {
  resources: [{
    resource: BlogPost,
    options: {},
    features: [blogFeature({
      // your options goes here
    })]
  }]
}

const adminBro = new AdminBro(options)
// and the rest of your app

The simplest case

@softwarebrothers/admin-bro-blog has lot's of configuration options but let's start with something super simple, an article with the following properties:

  • title, for storing post title
  • postUrl, for post URLs
  • body, here we will put content
  • excerpt, here we will put article excerpt
  • ogTags, here we will put metadata of open graph tags
  • status, and finally - blog post status: either published or a draft

Let's imagine that we already have a simple-blog model defined and this is our schema (typeorm example, written in typescript):


import { BlogPostMeta } from '@softwarebrothers/admin-bro-blog'

@Entity({ name: 'simple-blogs' })
export class SimpleBlog extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number;

  @Column({ nullable: false })
  public caption: string; // this is title

  @Column({ type: 'text' })
  public document: string; // this is body

  @Column()
  public status: string; // this is status

  @Column({ nullable: false })
  public slug: string; // this is postUrl

  @Column({ nullable: true })
  public shortDescription?: string; // this is excerpt

  @Column({ type: 'jsonb', nullable: true })
  public metaTags?: BlogPostMeta; // ogTags

  @CreateDateColumn()
  public createdAt: Date;

  @UpdateDateColumn()
  public updatedAt: Date;
}

type BlogPostMeta = {
  title?: string;
  description?: string;
}

Now go back to the settings section and lets map all these fields to the blogFeature()

  {
    features: [blogFeature({
      properties: {
        title: 'caption',
        body: 'document',
        status: 'status',
        postUrl: 'slug',
        excerpt: 'shortDescription',
        ogTags: 'metaTags',
      },
    })]
  }

And this is it. You have a running blog engine.

Adding photo upload

The basic case uses the native Quill Editor feature to add images to the content of a blog post as Base64 strings. This is ok for some cases but in general, you would like to change that to a regular upload.

So let's add:

  • option to upload post "splash" image (aka. postImage)
  • option to upload multiple images to the blog post content.

To do this we have to add to our schema 2 new 'mixed' properties. This will be of type jsob in our typeorm example.


import { BlogPostImage, BlogPostImages } from '@admin-bro/upload'

@Entity({ name: 'simple-blogs' })
export class SimpleBlog extends BaseEntity {
  // ... new properties
  @Column({type: 'jsonb', nullable: true  })
  public image?: BlogPostImage; // this will be an image

  @Column({ type: 'jsonb', nullable: true })
  public inlineImages?: BlogPostImages; // this will hold all inline images
}

and alter the ResourceOptions by defining your upload provider.

For reference check out the @admin-bro/upload plugin documentation

In the example, I will use Google Storage so I had to add to environmental variables 2 properties:

  • GOOGLE_APPLICATION_CREDENTIALS='path-to-your-json-file'
  • GOOGLE_STORAGE_MEDIA_BUCKET=name-of-your-bucket

Next, I have to install Google Cloud SDK for storage

yarn add @google-cloud/storage

and now I can go back to setup @softwarebrothers/admin-bro-blog

  {
    features: [blogFeature({
      properties: {
        title: 'caption',
        body: 'document',
        status: 'status',
        postUrl: 'slug',
        excerpt: 'shortDescription',
        ogTags: 'metaTags',
        postImage: 'image', // we mapped postImage to the image `mixed` property in db
        inlineImages: 'image', // we mapped postImage to the image `mixed` property in db
      },
      // this will be passed to @admin-bro/upload feature
      uploadProvider: {
        gcp: {
          bucket: process.env.GOOGLE_STORAGE_MEDIA_BUCKET as string,
        },
      },
    })]
  }

And this is it as well - now we can upload both splash image and "inline" images inside the editor.

Tags

The last things are tags. To add them you will have to have Tags model in the database and set tags property in the BlogOptions.

Let's start with tags model (typeorm example):

@Entity({ name: 'tags' })
export class Tag extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number;

  @Column({ nullable: true })
  public name: string;
}

Having it, you can now add tags to BlogOptions:

  {
    features: [blogFeature({
      properties: {
        title: 'caption',
        body: 'document',
        status: 'status',
        postUrl: 'slug',
        excerpt: 'shortDescription',
        ogTags: 'metaTags',
        postImage: 'image', // we mapped postImage to the image `mixed` property in db
        inlineImages: 'image', // we mapped postImage to the image `mixed` property in db
      },
      // this will be passed to @admin-bro/upload fature
      uploadProvider: {
        gcp: {
          bucket: process.env.GOOGLE_STORAGE_MEDIA_BUCKET as string,
        },
      },
      tags: {
        // under this property AdminBro will store all tags in BlogPost
        property: 'tags',
        // we created `Tag` model in typeorm. Basically this is what
        // you see when you click tags in the path: `admin/resources/__HERE__/records`
        resourceId: 'Tag',
        // column responsible for holding tag name
        nameColumn: 'name',
      },
    })]
  }

Lastly, we have to update the SimpleBlog entity by adding tags array:

@Entity({ name: 'simple-blogs' })
export class SimpleBlog extends BaseEntity {
  // this will be array of numbers because we hold references in this format.
  @Column({type: 'jsonb', nullable: true  })
  public tags?: Array<number>;
}

All options

For the list of all available options, you can take a look at BlogOptions below.

Example

in the repository there is an example-app folder - check it out if you need more information.

View Source admin-bro-blog/src/index.ts, line 2

Type Definitions

object

# BlogOptions

Configuration options for @softwarebrothers/admin-bro-blog feature

Properties:
Name Type Attributes Description
properties object
title string

Database property holding post title: should be a string type

body string

Database property holding html body: should allow to save long texts

status string

Property holding post status

postUrl string <optional>

URL of the post - so called slug. It is optional but highly recommended.

excerpt string <optional>

A brief information regarding the Blog post. Blog excerpts give your readers a taste or, teaser of a full blog post. When visitors see an excerpt that grabs their attention,, they can click the title, image, or Read More link to open the full post.

ogTags string <optional>

OpenGraph Tags which should be placed in the head of the page.

facebookMeta string <optional>

Similar to ogTags - facebook meta also has to be of type mixed which allows to add title, and description sub-properties

twitterMeta string <optional>

Similar to ogTags - twitter meta also has to be of type mixed which allows to add title, and description sub-properties

postImage string <optional>

Post image holds the main image which will be assigned to the post. You should use here, a mixed type which will hold: 'key', 'mimeType', 'bucket', 'size' sub-properties, required, by @admin-bro/upload. To use postImage you have to fill uploadProvider options as well.

inlineImages string <optional>

Inline images holds the images uploaded by the editor. Property selected here should be, a mixed type which will hold: 'key', 'mimeType', 'bucket', 'size' sub-properties as arrays., This is required by @admin-bro/upload., To use inlineImages you have to fill uploadProvider options as well.

updatedAt string <optional>

updatedAt column which is used to hold the information about the update date.

tags object <optional>

Set in case blog should have tags. Tags are implemented as one to many

property string
resourceId string
nameColumn string <optional>
uploadProvider UploadOptionsProvider <optional>

Upload provider options passed to @admin-bro/upload peerDependency., If you use either postImage or inlineImages you have to make sure that this is set.

View Source admin-bro-blog/src/types/blog-options.type.ts, line 20

object

# BlogPostImage

Type for an mixed property stored in the database responsible for photoImage You can use it in your TypeScript schema like this:

import { BlogPostImage } from '@softwarebrothers/admin-bro-blog'
Properties:
Name Type Description
key string

property holding object key (uploaded path)

mime string

mime type of uploaded file

bucket string

bucket (folder) where file has been stored

size number

size of the uploaded file

View Source admin-bro-blog/src/types/blog-post-image.type.ts, line 12

object

# BlogPostMeta

Type for an mixed property stored in the database responsible for meta tags like ogTags, facebookMeta and twitterMeta

Properties:
Name Type Description
title string

Meta title

description string

Meta description

View Source admin-bro-blog/src/types/blog-post-meta.type.ts, line 3

object

# BlogPostImages

Similar to BlogPostImage but for mixed property stored in the database responsible for inlineImages.

Properties:
Name Type Description
key Array.<string>

Array holding object keys (uploaded path)

mimeType Array.<string>

Array holding mime types

bucket Array.<string>

Array holding buckets (folders)

size Array.<number>

Array holding sizes

View Source admin-bro-blog/src/types/blog-post-image.type.ts, line 33

SoftwareBrothers

Proudly built and maintained by SoftwareBrothers

Software House with a passion for both JavaScript and TypeScript.

See what we do See what we believe in

Proudly built and maintained by

SoftwareBrothers