0.0.38 • Published 2 years ago

@connectnow/cn-vue-component-library v0.0.38

Weekly downloads
-
License
-
Repository
-
Last release
2 years ago

ConnectNow Component Library for Vue

Official ConnectNow component library used for ConnectNow applications on VueJS 3. Make sure to check out the "Required dependencies" section to see what also needs to be included in your project.

Required dependencies

See: peerDependencies in package.json for latest list. You must have these dependencies in your project for the component library to fully work.

"@connectnow/hedgehog": "^0.1.20",
"axios": "^0.21.x",
"vue": "^3.0.x",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"

Installing

In your main project, run:

npm i @connectnow/cn-vue-component-library

Components

You can import components as needed with:

import { CnInput, CnButton, CnCard, CnAvatar } from "@connectnow/cn-vue-component-library";

All components will appropriately pass any "standard tags", like "class" and "style". Note, that if you pass an attribute that is already used in the component, you will override it (example: <cn-button class="link" /> will delete the default "button" class that usually exists on the element).

CnInput

Use showLabel to determine if a label should be rendered. Set the label attribute to set the labels text - otherwise it will default to text defined in the placeholder attribute. Use showIfRequired to show additional information in the label if the input also has required="required" set.

Setting the help attribute to a string will render additional help-text below the input.

Set the errors attribute to an array of strings containing errors. This will show an error state for the input and render red help-text below the input (overriding the help attribute).

When using inputs specified as type=checkbox or type=radio, you can pass an options array of strings containing possible values for the radio or checkbox inputs.

CnButton

CnButton renders a dynamic button. If you specify a to attribute, a router-link will be generated. If you specify an href attribute, then an <a> element will be created. Otherwise, a button element is rendered.

If you would like the button to render as a link, you can set type="link" as an attribute on the component.

You can show a loading state by passing :isLoading="true". Note that if you are overriding the disabled attribute, you will also have to make sure that disabled is true when isLoading is also true.

CnCard

Set the title and subtitle to set the title and subtitle of the card respectively. imgUrl, if provided, will display a card image.

Set actions to an array of objects containing key-value pairs that you can pass to CnInput. This will render the appropriate buttons on the card.

This component also has slots. The default slot will override the card body, while the actions named slot will replace any buttons/actions in your card.

CnAvatar

Set name, surname, and email attributes so that the component can compute colors and a Gravatar.

Use color to define a custom color to use for the background of the avatar. If not set, one will be computed from the name and surname.

Set useImage to true so that the component displays an image rather than an icon with the users initials. If url is set, it will use that url for the image, otherwise it will try to get a Gravatar using the email attribute.

Set size to define the size of the avatar in pixels. Default is 40.

CnLogo

If logoUrl is set, it will use that url for the image, otherwise it will show the default ConnectNow logo in SVG.

Set size to define the size of the avatar in pixels. Default is 50.

Set the title as needed with the title attribute, or keep it off for the ConnectNow default. You can set its color property with titleColor, or you can hide the title by adding :showTitle="false".

The logo is also a navigational component, which by default takes you to the homepage. You can set what page it should link to with the link attribute;

CnBox

The box component is designed to faciltiate the bulk of the "panel" displays throughout the apps. Entirely custom content can be displayed, the component can query the CN Api on its own to display a collection or object, or a custom object or collection can be passed to display. See serve.vue for 3 unique examples.

Custom content

Custom content can be handled with slots and overriding the inner HTML of the component.

To change the title to something custom, place the following slot template within the component:

<cn-box
  :showCount="true|false"
  ...
>
  <template v-slot:header>
    <h2>Company user info</h2>
  </template>
</cn-box>

To completely override the content to something custom, simply place your HTML within the component tags.

<cn-box>
  <template v-slot:header>
    <h2>Custom title</h2>
  </template>
  <form>
    ...
  </form>
  </div>
</cn/box>

Displaying a model or collection

Pass modelName to control the target model of the component, changing the API endpoint and various labels.

The title of the box will be inferred from the modelName, but can be overridden with modelLabel. modelLabel is an array to facilitate pluralisation. The [0] index is singular, the [1] plural. E.g. pass :modelLabel="['Active User','Active Users']" to have the title show as "User" and "Users" respectively depending on the count.

Pass showCount="true" to show a count of the records returned by the active filters.

Pass :showHeaderButton="true" to place a button on the top right of the container. The text can be controlled with headerButtonText and a callback function attached with :headerButtonCallback="functionName" that will execute functionName() when clicked.

Pass :listItemsClickable="false" to disable click events on each row. When clickable, the app will navigate to /admin/{{modelName}}/{{id}} when a row is clicked.

By default, items that are disabled/deleted etc are marked with a strikeout. Pass :strikeoutDisabledItems="false" to disable this.

Populating results

Pass :useFetchModel="true" to have the component call the underling API. This will call the index endpoint of the corresponding modelName, passing the active Company along. To pull data from another endpoint, use the initialData prop (below).

The initialData prop allows the box to be populated with a custom recordset.

You can pass an array to the scopes and with parameters to be fed to the underlying API call used when useFetchModel is true. E.g. pass :scopes="['active', 'latest']" to pass the "active" and "latest" scopes.

The newRecord prop can be used to easily add a new entry to the results without re-querying an API. This is useful if your object is not controlled via state where you cannot call an action or mutate to add a new entry globally. You could hit the API again, or you could insert the new entry with newRecord. This prop is watched and when the value changes, the object will be pushed to the internal results of the component.

Specifying which properties to display from the model in the data rows

The two rows of text on each row can be controlled with modelPrimaryParameters and modelSecondaryParameters. These props can consist an array of dot-notation strings to traverse the object looking for properties to display.

For example, take the following data:

[
  {
    name: Kagami,
    surname: Kurosawa,
    email: Kurosawa,
    security: {
      role: "admin"
    }
    companies: [
      {
        id: 1,
        name: "Company 1"
      },
      ...
    ]
  },
  ...
]

To display the first name and surname you would use :model{{Primary | Secondary}}Parameters="['name', 'surname']". When provided multiple properties, they are joined together by a space. To change the character that is used pass {{primary|secondary}}JoinDelimiter=" - ".

Box can drill down one level in to a nested object to grab a prop. To display this user's role, you would use :model{{Primary | Secondary}}Parameters="['security.role']".

If provided an array, box will display a count. To display a count of this user's companies, you would use :model{{Primary | Secondary}}Parameters="['companies']".

By default, box will look for ['name'] for primary, and ['id'] for secondary.

Tip: The following functionality exists as a convenience for simpler use cases where box targets an API with :fetchModel="true" and displays the raw response. A better route for complex situations that require significant manipulation, or with many nested objects would be to feed the Box component a ready-to-view object/collection via :initialData with :useFetchModel="false" (default). This way no transforms or display controls would be required at all as the box simply displays the data exactly as provided,

Displaying only specified properties in a model view

By default all properties of a model are displayed. Pass :displayProps="['name','of','properties', 'nested.prop']" to specify a list of properties to display and ignore the rest. Box can look for a display prop one object deep, i.e. user.email.

Transforming values

By default each property is transformed from snake_case and its data type inspected and formatted. In the case of viewing entire models and their properties, often the property names used for labelling are not user friendly and need transforming as they come straight from a database. To transform values, pass :labelTransformations="my_transforms". The data passed should be an array of objects as follows:

[
  {
    original: "current_thing_to_look_for_name",
    transformed" "New name"
  },
  ...
]

Any matches within the dataset will be replaced.

Both model{{Primary | Secondary}}Parameters can be prefixed or suffixed with a custom value in order to provide a clearer description of what the value represents. Use primaryPrefix, secondaryPrefix, primarySuffix, and secondarySuffix to add text before/after the displayed value. E.g:

Searching / filtering and ordering results

Pass :hasSearch="true" to show a search/filter input. The filter will target the :modelPrimaryParameters value(s) for filtering. Pass orderBy="prop" to order the results by the specified property. By default, the order will respect the order from the API or HTML. Pass :orderByAscending="true" to order the results in descending order instead of ascending.

API wrapper

You can also import the Axios API wrapper, like so:

import api from "@connectnow/cn-vue-component-library/src/api/general";

When using the API, remember to set VUE_APP_CN_API_BASE in a .env file, pointing to your API base URL, like so VUE_APP_CN_API_BASE=http://localhost/api/.

Auth store module

Import the authentication store by using the auth store module (in your router index page):

import { createStore } from "vuex";
import auth from "@connectnow/cn-vue-component-library/src/store/auth";

export default createStore({
  modules: {
    auth,
  },
  ...
});

Auth routes

The component library comes with common routes for authentication. You can import and use these routes in our project with:

import { createRouter } from "vue-router";
import { authRoutes, handleAuthBeforeResolve } from "./auth"
import store from "@/store";

const routes = [
  authRoutes,
  ...
];

const router = createRouter({
  routes,
  ...
});

NOTE: it may be best to manually copy the authRoutes code and define it explicitly in your project - mapping it to the appropriate auth views in your app.

To handle authentication and basic authorization, you should also add a beforeResolve to the router, with an instance of the store. This will automatically verify authentication and redirect as needed. Here's an example:

router.beforeEach(async (to) => {
  const redirectUrl = await handleAuthBeforeResolve(to, store);
  return redirectUrl;
});

export default router;

Change where the router redirects to when the user is authenticated but maybe doesn't have permission to view a given page, using an optional third parameter. By default, this is /admin. Alternatively, you can write your own handler for checking authentication.

Error pages

You can use the 404 page in your router with the following entry into your routes declaration:

{
    path: "/:pathMatch(.*)*",
    component: () =>
      import(
        /* webpackChunkName: "issues" */ "@connectnow/cn-vue-component-library/src/error-pages/Cn404.vue"
      ),
  },

Notifications

Import browser notifications using:

import browserNotifications from "@connectnow/cn-vue-component-library/src/notifications/browser";

Then, in your code somewhere, you can use this code to send a browser notification if the tab is not in focus:

browserNotifications.notify(text);

Helpers

MD5

The MD5 helper is used internally to compute data needed for Gravatar. If needed, you can use it too:

import md5 from "@connectnow/cn-vue-component-library/src/helpers/md5";

debounce

The debounce helper provides a simple, easy debounce to use. Import it with the following:

import debounce from "@connectnow/cn-vue-component-library/src/helpers/debounce";

Local building of this library

npm run serve

Then, in your main project, you can install via NPM with absolute path. Note, npm link doesn't work, so use the pack approach: https://stackoverflow.com/a/62875291/7410951.

For detailed info developing with this framework, see: https://github.com/team-innovation/vue-sfc-rollup

0.0.37

2 years ago

0.0.38

2 years ago

0.0.23

2 years ago

0.0.24

2 years ago

0.0.25

2 years ago

0.0.30

2 years ago

0.0.31

2 years ago

0.0.32

2 years ago

0.0.33

2 years ago

0.0.34

2 years ago

0.0.35

2 years ago

0.0.36

2 years ago

0.0.23-rc.1

2 years ago

0.0.26

2 years ago

0.0.27

2 years ago

0.0.28

2 years ago

0.0.29

2 years ago

0.0.20

3 years ago

0.0.21

3 years ago

0.0.22

3 years ago

0.0.16

3 years ago

0.0.17

3 years ago

0.0.18

3 years ago

0.0.19

3 years ago

0.0.11

3 years ago

0.0.12

3 years ago

0.0.13

3 years ago

0.0.14

3 years ago

0.0.15

3 years ago

0.0.10

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago