From 68c625ec79bd1a8878e96cb1bc773eef49a1114d Mon Sep 17 00:00:00 2001 From: Rijk van Zanten Date: Thu, 12 Mar 2020 12:31:36 -0400 Subject: [PATCH] Document and structure utils / compositions (#168) * Document and structure utils / compositions * Fix tests * Ignore tests in sonar cloud? * Please sonar don't use my test files --- sonar-project.properties | 4 +- .../v-item-group/v-item-group.test.ts | 2 +- src/components/v-item-group/v-item.test.ts | 2 +- .../{ => groupable}/groupable.test.ts | 2 +- src/compositions/{ => groupable}/groupable.ts | 2 +- src/compositions/groupable/index.ts | 4 + src/compositions/groupable/readme.md | 63 ++++++++++++ src/compositions/readme.md | 97 +------------------ src/compositions/size-class/index.ts | 4 + src/compositions/size-class/readme.md | 28 ++++++ .../{ => size-class}/size-class.test.ts | 2 +- .../{ => size-class}/size-class.ts | 0 src/compositions/use-event-listener/index.ts | 4 + src/compositions/use-event-listener/readme.md | 19 ++++ .../use-event-listener.test.ts | 2 +- .../use-event-listener.ts | 0 src/compositions/use-time-from-now/readme.md | 16 +++ .../use-time-from-now.test.ts | 2 +- .../use-time-from-now.ts | 0 src/compositions/use-window-size/readme.md | 16 +++ .../use-window-size.test.ts | 2 +- .../{ => use-window-size}/use-window-size.ts | 0 src/interfaces/register.ts | 2 +- src/layouts/register.ts | 2 +- src/stores/collections/collections.ts | 2 +- src/stores/fields/fields.ts | 2 +- src/styles/readme.md | 7 +- .../arrays-are-equal.test.ts | 0 .../arrays-are-equal.ts | 6 -- src/utils/arrays-are-equal/index.ts | 4 + src/utils/arrays-are-equal/readme.md | 15 +++ src/utils/is-empty/index.ts | 4 + src/utils/{ => is-empty}/is-empty.test.ts | 0 src/utils/{ => is-empty}/is-empty.ts | 0 src/utils/is-empty/readme.md | 30 ++++++ src/utils/readme.md | 6 +- src/utils/register-component/index.ts | 4 + src/utils/register-component/readme.md | 13 +++ .../register-component.test.ts | 0 .../register-component.ts | 0 .../drawer-detail/drawer-detail.test.ts | 2 +- src/views/readme.md | 9 +- 42 files changed, 260 insertions(+), 119 deletions(-) rename src/compositions/{ => groupable}/groupable.test.ts (99%) rename src/compositions/{ => groupable}/groupable.ts (99%) create mode 100644 src/compositions/groupable/index.ts create mode 100644 src/compositions/groupable/readme.md create mode 100644 src/compositions/size-class/index.ts create mode 100644 src/compositions/size-class/readme.md rename src/compositions/{ => size-class}/size-class.test.ts (96%) rename src/compositions/{ => size-class}/size-class.ts (100%) create mode 100644 src/compositions/use-event-listener/index.ts create mode 100644 src/compositions/use-event-listener/readme.md rename src/compositions/{ => use-event-listener}/use-event-listener.test.ts (94%) rename src/compositions/{ => use-event-listener}/use-event-listener.ts (100%) create mode 100644 src/compositions/use-time-from-now/readme.md rename src/compositions/{ => use-time-from-now}/use-time-from-now.test.ts (97%) rename src/compositions/{ => use-time-from-now}/use-time-from-now.ts (100%) create mode 100644 src/compositions/use-window-size/readme.md rename src/compositions/{ => use-window-size}/use-window-size.test.ts (93%) rename src/compositions/{ => use-window-size}/use-window-size.ts (100%) rename src/utils/{ => arrays-are-equal}/arrays-are-equal.test.ts (100%) rename src/utils/{ => arrays-are-equal}/arrays-are-equal.ts (70%) create mode 100644 src/utils/arrays-are-equal/index.ts create mode 100644 src/utils/arrays-are-equal/readme.md create mode 100644 src/utils/is-empty/index.ts rename src/utils/{ => is-empty}/is-empty.test.ts (100%) rename src/utils/{ => is-empty}/is-empty.ts (100%) create mode 100644 src/utils/is-empty/readme.md create mode 100644 src/utils/register-component/index.ts create mode 100644 src/utils/register-component/readme.md rename src/utils/{ => register-component}/register-component.test.ts (100%) rename src/utils/{ => register-component}/register-component.ts (100%) diff --git a/sonar-project.properties b/sonar-project.properties index e13e0ec2e3..ba3104fddb 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -2,9 +2,7 @@ sonar.organization=directus sonar.projectKey=app-next sonar.sources=src -sonar.exclusions=src/**/*.story.ts -sonar.test.sources=src/**/*.test.ts -sonar.test.exclusions=src/**/*.test.ts +sonar.exclusions=src/**/*.story.ts,src/**/*.test.ts sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.testExecutionReportPaths=coverage/sonar.xml diff --git a/src/components/v-item-group/v-item-group.test.ts b/src/components/v-item-group/v-item-group.test.ts index 00eeebed63..1f2b0b663b 100644 --- a/src/components/v-item-group/v-item-group.test.ts +++ b/src/components/v-item-group/v-item-group.test.ts @@ -1,7 +1,7 @@ import { mount, createLocalVue } from '@vue/test-utils'; import VueCompositionAPI from '@vue/composition-api'; import VItemGroup from './v-item-group.vue'; -import * as composition from '@/compositions/groupable'; +import * as composition from '@/compositions/groupable/groupable'; const localVue = createLocalVue(); localVue.use(VueCompositionAPI); diff --git a/src/components/v-item-group/v-item.test.ts b/src/components/v-item-group/v-item.test.ts index 1ed1091bf8..ea901d4607 100644 --- a/src/components/v-item-group/v-item.test.ts +++ b/src/components/v-item-group/v-item.test.ts @@ -1,7 +1,7 @@ import { mount, createLocalVue } from '@vue/test-utils'; import VueCompositionAPI from '@vue/composition-api'; import VItem from './v-item.vue'; -import * as composition from '@/compositions/groupable'; +import * as composition from '@/compositions/groupable/groupable'; const localVue = createLocalVue(); localVue.use(VueCompositionAPI); diff --git a/src/compositions/groupable.test.ts b/src/compositions/groupable/groupable.test.ts similarity index 99% rename from src/compositions/groupable.test.ts rename to src/compositions/groupable/groupable.test.ts index d909fa3794..b61fd1439b 100644 --- a/src/compositions/groupable.test.ts +++ b/src/compositions/groupable/groupable.test.ts @@ -1,6 +1,6 @@ import Vue from 'vue'; import { provide, inject, ref } from '@vue/composition-api'; -import mountComposition from '../../.jest/mount-composition'; +import mountComposition from '../../../.jest/mount-composition'; import { useGroupable, useGroupableParent } from './groupable'; describe('Groupable', () => { diff --git a/src/compositions/groupable.ts b/src/compositions/groupable/groupable.ts similarity index 99% rename from src/compositions/groupable.ts rename to src/compositions/groupable/groupable.ts index 3d81d755be..5839ccd988 100644 --- a/src/compositions/groupable.ts +++ b/src/compositions/groupable/groupable.ts @@ -1,6 +1,6 @@ import Vue from 'vue'; import { computed, onBeforeUnmount, inject, ref, provide, Ref, watch } from '@vue/composition-api'; -import { notEmpty, isEmpty } from '@/utils/is-empty'; +import { notEmpty, isEmpty } from '@/utils/is-empty/'; type GroupableInstance = { active: Ref; diff --git a/src/compositions/groupable/index.ts b/src/compositions/groupable/index.ts new file mode 100644 index 0000000000..802023c2ae --- /dev/null +++ b/src/compositions/groupable/index.ts @@ -0,0 +1,4 @@ +import { useGroupable, useGroupableParent } from './groupable'; + +export { useGroupable, useGroupableParent }; +export default { useGroupable, useGroupableParent }; diff --git a/src/compositions/groupable/readme.md b/src/compositions/groupable/readme.md new file mode 100644 index 0000000000..120d928369 --- /dev/null +++ b/src/compositions/groupable/readme.md @@ -0,0 +1,63 @@ +# `useGroupable` / `useGroupableParent` +Can be used to make a selectable group of items within a parent container. This is used to facilitate +the functionality of the `v-item-group` base component, and other groupable components like `detail-group`, +`button-group`. + +## Usage + +Use the `useGroupableParent` function in a parent component that will contain one or more components +in it's slots (deeply nested or not) that use the `useGroupable` compositions. + +### `useGroupableParent(state: GroupableParentState, options: GroupableParentOptions): void` + +The `useGroupableParent` composition accepts two paremeters: state and options. +State includes a `selection` key that can be used to pass an array of selected items, so you can +manage this active state from the parent context. The `onSelectionChange` property of state is a +callback function that fires whenever the selection changes from a child groupable item. + +The `options` parameter can be used to set some behavioral options for the selection logic. These +options include `multiple: boolean`, `max: number`, `mandatory: boolean`. + +```js +import { defineComponent } from '@vue/composition-api'; +import { useGroupableParent } from '@/compositions/size-class/'; + +export default defineComponent({ + props: { + ...sizeProps + }, + setup(props) { + useGroupableParent( + { + selection: selection, + onSelectionChange: newSelectionValues => emit('input', newSelectionValues) + }, + { + multiple: multiple, + max: max, + mandatory: mandatory + } + ); + } +}); +``` + +### `useGroupable(value: string | number): { active: Ref; toggle: () => void; }` +Registers this component as a child of the first parent component that uses the `useGroupableParent` +component. + +The `useGroupable` composition accepts a single parameter (`value`) that will be used in the selection +state of the groupable parent. The composition returns an object with the active state, and a function +that will toggle this component's active state in the parent's selection. + +```js +import { defineComponent } from '@vue/composition-api'; +import { useGroupable } from '@/compositions/groupable'; + +export default defineComponent({ + setup(props) { + const { active, toggle } = useGroupable('unique-value-for-this-item'); + return { active, toggle }; + } +}); +``` diff --git a/src/compositions/readme.md b/src/compositions/readme.md index ff3f7b8358..59fa17de87 100644 --- a/src/compositions/readme.md +++ b/src/compositions/readme.md @@ -4,95 +4,8 @@ Compositions are reusable pieces of logic that can be used inside Vue components ## Table of Contents -* [Event Listener](#event-listener) -* [Size Class](#size-class) -* [Time from Now](#time-from-now) -* [Window Size](#window-size) - -## Event Listener - -The event listener composition allows you to bound event listeners to global elements. - -**Note:** You should rely on Vue's event handlers like `@click` whenever possible. This composition acts as an escape hatch for triggering things based on out-of-component events. - -The composition removes the event handler whenever the component is unmounted. - -### Usage - -```js -import { defineComponent } from '@vue/composition-api'; -import useEventListener from '@/compositions/use-event-listener'; - -export default defineComponent({ - setup() { - useEventListener(window, 'scroll', onScroll); - - function onScroll(event) { - console.log(event); - } - } -}); -``` - ---- - -## Size Class - -Shared size class prop handler for base components. Adds `x-small`, `small`, `large`, and `x-large` props to the component, and converts the prop into a string that can be added to classes. - -### Usage - -```js -import { defineComponent } from '@vue/composition-api'; -import useSizeClass, { sizeProps } from '@/compositions/size-class'; - -export default defineComponent({ - props: { - ...sizeProps - }, - setup(props) { - const sizeClass = useSizeClass(props); - } -}); -``` - ---- - -## Time from Now - -Returns ref string time from current datetime based on date-fns formatDistance. - -### Usage - -```js -import { defineComponent } from '@vue/composition-api'; -import useTimeFromNow from '@/compositions/use-time-from-now'; - -export default defineComponent({ - setup() { - const date = new Date('2020-01-01T13:55'); - const timeFromNow = useTimeFromNow(date); - } -}); -``` - -The composition accepts an optional second parameter that controls how often the value is update. You can set this to `0` if you don't want the value to update at all. - ---- - -## Window Size - -Returns a `ref` of `width` and `height` of the current window size. Updates the value on window resizes. - -### Usage - -```js -import { defineComponent } from '@vue/composition-api'; -import useWindowSize from '@/compositions/window-size'; - -export default defineComponent({ - setup() { - const { width, height } = useWindowSize(); - } -}); -``` +* [`useGroupable` / `useGroupableParent`](./groupable) +* [`useSizeClass`](./size-class) +* [`useEventListener`](./use-event-listener) +* [`useTimeFromNow`](./use-time-from-now) +* [`useWindowSize`](./use-window-size) diff --git a/src/compositions/size-class/index.ts b/src/compositions/size-class/index.ts new file mode 100644 index 0000000000..2b94ee6be5 --- /dev/null +++ b/src/compositions/size-class/index.ts @@ -0,0 +1,4 @@ +import useSizeClass, { sizeProps } from './size-class'; + +export { sizeProps, useSizeClass }; +export default useSizeClass; diff --git a/src/compositions/size-class/readme.md b/src/compositions/size-class/readme.md new file mode 100644 index 0000000000..53cf682f18 --- /dev/null +++ b/src/compositions/size-class/readme.md @@ -0,0 +1,28 @@ +# Size Class +Set of props and a composition that can inject a standardized sizing prop for components. + +A component that uses this composition and the corresponding props will accept the `x-small` through +`x-large` props: + +```html + + + + +``` + +## Usage +```js +import { defineComponent } from '@vue/composition-api'; +import useSizeClass, { sizeProps } from '@/compositions/size-class/'; + +export default defineComponent({ + props: { + ...sizeProps + }, + setup(props) { + const sizeClass = useSizeClass(props); + return { sizeClass }; // one of x-small, small, large, x-large + } +}); +``` diff --git a/src/compositions/size-class.test.ts b/src/compositions/size-class/size-class.test.ts similarity index 96% rename from src/compositions/size-class.test.ts rename to src/compositions/size-class/size-class.test.ts index d041d9dfc6..a01dcb878a 100644 --- a/src/compositions/size-class.test.ts +++ b/src/compositions/size-class/size-class.test.ts @@ -1,5 +1,5 @@ import useSizeClass from './size-class'; -import mountComposition from '../../.jest/mount-composition'; +import mountComposition from '../../../.jest/mount-composition'; describe('Compositions / Size Class', () => { it('Extracts the correct class based on given props', () => { diff --git a/src/compositions/size-class.ts b/src/compositions/size-class/size-class.ts similarity index 100% rename from src/compositions/size-class.ts rename to src/compositions/size-class/size-class.ts diff --git a/src/compositions/use-event-listener/index.ts b/src/compositions/use-event-listener/index.ts new file mode 100644 index 0000000000..d753738fd3 --- /dev/null +++ b/src/compositions/use-event-listener/index.ts @@ -0,0 +1,4 @@ +import useEventListener from './use-event-listener'; + +export { useEventListener }; +export default useEventListener; diff --git a/src/compositions/use-event-listener/readme.md b/src/compositions/use-event-listener/readme.md new file mode 100644 index 0000000000..ac703c512c --- /dev/null +++ b/src/compositions/use-event-listener/readme.md @@ -0,0 +1,19 @@ +# `useEventListener(target: HTMLElement, type: string, handler: (event: Event) => void, options: AddEventListenerOptions): void` +Can be used to attach an event listener to any DOM element that will automatically be attached / +cleaned up whenever the component mounts / unmounts. + +## Usage +```js +import { defineComponent } from '@vue/composition-api'; +import { useEventListener } from '@/compositions/use-event-listener'; + +export default defineComponent({ + setup(props) { + useEventListener(document.querySelector('#example'), 'click', onExampleClick); + + function onExampleClick(event) { + // ... + } + } +}); +``` diff --git a/src/compositions/use-event-listener.test.ts b/src/compositions/use-event-listener/use-event-listener.test.ts similarity index 94% rename from src/compositions/use-event-listener.test.ts rename to src/compositions/use-event-listener/use-event-listener.test.ts index a6d9147226..aaa9169e01 100644 --- a/src/compositions/use-event-listener.test.ts +++ b/src/compositions/use-event-listener/use-event-listener.test.ts @@ -1,6 +1,6 @@ import { ref } from '@vue/composition-api'; import useEventListener from './use-event-listener'; -import mountComposition from '../../.jest/mount-composition'; +import mountComposition from '../../../.jest/mount-composition'; describe('Compositions / Event Listener', () => { it('Adds passed event listener onMounted', () => { diff --git a/src/compositions/use-event-listener.ts b/src/compositions/use-event-listener/use-event-listener.ts similarity index 100% rename from src/compositions/use-event-listener.ts rename to src/compositions/use-event-listener/use-event-listener.ts diff --git a/src/compositions/use-time-from-now/readme.md b/src/compositions/use-time-from-now/readme.md new file mode 100644 index 0000000000..681c08bc7f --- /dev/null +++ b/src/compositions/use-time-from-now/readme.md @@ -0,0 +1,16 @@ +# `useTimeFromNow(date: Date | number, autoUpdate: number = 60000): Ref +Composition that can be used to create a relative time format that is auto updated every `autoUpdate` +milliseconds. + +## Usage +```js +import { defineComponent } from '@vue/composition-api'; +import { useTimeFromNow } from '@/compositions/use-time-from-now'; + +export default defineComponent({ + setup(props) { + const timeFromNow = useTimeFromNow(Date.now()); + return { timeFromNow }; + } +}); +``` diff --git a/src/compositions/use-time-from-now.test.ts b/src/compositions/use-time-from-now/use-time-from-now.test.ts similarity index 97% rename from src/compositions/use-time-from-now.test.ts rename to src/compositions/use-time-from-now/use-time-from-now.test.ts index 30053345c7..58f4cefd47 100644 --- a/src/compositions/use-time-from-now.test.ts +++ b/src/compositions/use-time-from-now/use-time-from-now.test.ts @@ -1,6 +1,6 @@ import { Ref } from '@vue/composition-api'; import useTimeFromNow from './use-time-from-now'; -import mountComposition from '../../.jest/mount-composition'; +import mountComposition from '../../../.jest/mount-composition'; import mockdate from 'mockdate'; describe('Compositions / Event Listener', () => { diff --git a/src/compositions/use-time-from-now.ts b/src/compositions/use-time-from-now/use-time-from-now.ts similarity index 100% rename from src/compositions/use-time-from-now.ts rename to src/compositions/use-time-from-now/use-time-from-now.ts diff --git a/src/compositions/use-window-size/readme.md b/src/compositions/use-window-size/readme.md new file mode 100644 index 0000000000..1eade6552d --- /dev/null +++ b/src/compositions/use-window-size/readme.md @@ -0,0 +1,16 @@ +# useWindowSize(options: WindowSizeOptions = { throttle: 100 }): { width: Ref; height: Ref; } +Returns the window's width and height in an object. These values are reactive. + +The optional `options` parameter allows you to set the throttling speed. + +## Usage +```js +import { defineComponent } from '@vue/composition-api'; +import { useWindowSize } from '@/compositions/use-window-size/'; + +export default defineComponent({ + setup(props) { + const { width, height } = useWindowSize(); + } +}); +``` diff --git a/src/compositions/use-window-size.test.ts b/src/compositions/use-window-size/use-window-size.test.ts similarity index 93% rename from src/compositions/use-window-size.test.ts rename to src/compositions/use-window-size/use-window-size.test.ts index 42f5e3ac0e..06e7a84d77 100644 --- a/src/compositions/use-window-size.test.ts +++ b/src/compositions/use-window-size/use-window-size.test.ts @@ -1,6 +1,6 @@ import { watch } from '@vue/composition-api'; import useWindowSize from './use-window-size'; -import mountComposition from '../../.jest/mount-composition'; +import mountComposition from '../../../.jest/mount-composition'; describe('Compositions / Window Size', () => { it('Adds passed event listener onMounted', async () => { diff --git a/src/compositions/use-window-size.ts b/src/compositions/use-window-size/use-window-size.ts similarity index 100% rename from src/compositions/use-window-size.ts rename to src/compositions/use-window-size/use-window-size.ts diff --git a/src/interfaces/register.ts b/src/interfaces/register.ts index aae966569a..8ce4fa7cd8 100644 --- a/src/interfaces/register.ts +++ b/src/interfaces/register.ts @@ -1,4 +1,4 @@ -import registerComponent from '@/utils/register-component'; +import registerComponent from '@/utils/register-component/'; import interfaces from './index'; // inter, cause interface is reserved keyword in JS... o_o diff --git a/src/layouts/register.ts b/src/layouts/register.ts index 9ba1079cb3..f6a0b21ec1 100644 --- a/src/layouts/register.ts +++ b/src/layouts/register.ts @@ -1,4 +1,4 @@ -import registerComponent from '@/utils/register-component'; +import registerComponent from '@/utils/register-component/'; import layouts from './index'; layouts.forEach(layout => { diff --git a/src/stores/collections/collections.ts b/src/stores/collections/collections.ts index 0e89bae511..5dd686c7f7 100644 --- a/src/stores/collections/collections.ts +++ b/src/stores/collections/collections.ts @@ -3,7 +3,7 @@ import api from '@/api'; import { Collection, CollectionRaw } from './types'; import { useProjectsStore } from '@/stores/projects'; import i18n from '@/lang/'; -import { notEmpty } from '@/utils/is-empty'; +import { notEmpty } from '@/utils/is-empty/'; import VueI18n from 'vue-i18n'; import formatTitle from '@directus/format-title'; diff --git a/src/stores/fields/fields.ts b/src/stores/fields/fields.ts index 36657f01e2..93f4f3058a 100644 --- a/src/stores/fields/fields.ts +++ b/src/stores/fields/fields.ts @@ -3,7 +3,7 @@ import { FieldRaw, Field } from './types'; import api from '@/api'; import { useProjectsStore } from '@/stores/projects'; import VueI18n from 'vue-i18n'; -import { notEmpty } from '@/utils/is-empty'; +import { notEmpty } from '@/utils/is-empty/'; import { i18n } from '@/lang'; import formatTitle from '@directus/format-title'; diff --git a/src/styles/readme.md b/src/styles/readme.md index 15e076b246..1ae1d30b96 100644 --- a/src/styles/readme.md +++ b/src/styles/readme.md @@ -1,5 +1,8 @@ # Styles -The global styles of the application. Even though everything is based around scoped styles in the components, there's still a need to have a certain set of global styles. Most importantly the global reset ([_base.scss](./_base.scss)) and CSS Custom Properties (variables) ([_variables.scss](./_variables.scss)). +The global styles of the application. Even though everything is based around scoped styles in the +components, there's still a need to have a certain set of global styles. Most importantly the global +reset ([_base.scss](./_base.scss)) and CSS Custom Properties (variables). -There are a couple of plugins (v-tooltip / codemirror / etc) that expect their styles to be global. This folder can be used for that as well. +There are a couple of third party plugins (codemirror / TinyMCE etc) that expect their styles to be +global. This folder can be used for that as well. diff --git a/src/utils/arrays-are-equal.test.ts b/src/utils/arrays-are-equal/arrays-are-equal.test.ts similarity index 100% rename from src/utils/arrays-are-equal.test.ts rename to src/utils/arrays-are-equal/arrays-are-equal.test.ts diff --git a/src/utils/arrays-are-equal.ts b/src/utils/arrays-are-equal/arrays-are-equal.ts similarity index 70% rename from src/utils/arrays-are-equal.ts rename to src/utils/arrays-are-equal/arrays-are-equal.ts index 1bc2fb503b..44328422a4 100644 --- a/src/utils/arrays-are-equal.ts +++ b/src/utils/arrays-are-equal/arrays-are-equal.ts @@ -1,9 +1,3 @@ -/** - * Compares two given arrays for equality. Only works for primitive values (no nested objects) - * @param a1 First array - * @param a2 Second array - * @see https://stackoverflow.com/a/55614659/4859211 - */ export default function arraysAreEqual( a1: readonly (string | number)[], a2: readonly (string | number)[] diff --git a/src/utils/arrays-are-equal/index.ts b/src/utils/arrays-are-equal/index.ts new file mode 100644 index 0000000000..7288f1714e --- /dev/null +++ b/src/utils/arrays-are-equal/index.ts @@ -0,0 +1,4 @@ +import arraysAreEqual from './arrays-are-equal'; + +export { arraysAreEqual }; +export default arraysAreEqual; diff --git a/src/utils/arrays-are-equal/readme.md b/src/utils/arrays-are-equal/readme.md new file mode 100644 index 0000000000..cb2566212b --- /dev/null +++ b/src/utils/arrays-are-equal/readme.md @@ -0,0 +1,15 @@ +# `arraysAreEqual` +Tests if two given arrays contain the same primitive values. **Note**: this _does not_ check object +equality in arrays. + +Based on https://stackoverflow.com/a/55614659/4859211 + +## Usage +```js +const arr1 = ['a', 'b', 'c']; +const arr2 = [1, 2, 3]; +const arr3 = ['a', 'b', 'c']; + +arraysAreEqual(arr1, arr2); // false +arraysAreEqual(arr1, arr3); // true +``` diff --git a/src/utils/is-empty/index.ts b/src/utils/is-empty/index.ts new file mode 100644 index 0000000000..a7e93ca10a --- /dev/null +++ b/src/utils/is-empty/index.ts @@ -0,0 +1,4 @@ +import { isEmpty, notEmpty } from './is-empty'; + +export { isEmpty, notEmpty }; +export default { isEmpty, notEmpty }; diff --git a/src/utils/is-empty.test.ts b/src/utils/is-empty/is-empty.test.ts similarity index 100% rename from src/utils/is-empty.test.ts rename to src/utils/is-empty/is-empty.test.ts diff --git a/src/utils/is-empty.ts b/src/utils/is-empty/is-empty.ts similarity index 100% rename from src/utils/is-empty.ts rename to src/utils/is-empty/is-empty.ts diff --git a/src/utils/is-empty/readme.md b/src/utils/is-empty/readme.md new file mode 100644 index 0000000000..0de2ee2982 --- /dev/null +++ b/src/utils/is-empty/readme.md @@ -0,0 +1,30 @@ +# `isEmpty` / `notEmpty` +Checks if the given value is `null` or `undefined`. Can be used in place of a simple "truthy" check: + +Before: `if (value) { ... }` + +After: `if (notEmpty(value)) { ... } + +## Usage +```js +const a = undefined; +const b = null; +const c = 'test'; +const d = 42; +const e = []; +const f = {}; + +isEmpty(a); // true +isEmpty(b); // true +isEmpty(c); // false +isEmpty(d); // false +isEmpty(e); // false +isEmpty(f); // false + +notEmpty(a); // false +notEmpty(b); // false +notEmpty(c); // true +notEmpty(d); // true +notEmpty(e); // true +notEmpty(f); // true +``` diff --git a/src/utils/readme.md b/src/utils/readme.md index 5aaa49364e..b531ec6d74 100644 --- a/src/utils/readme.md +++ b/src/utils/readme.md @@ -2,6 +2,8 @@ Various utility functions that can be reused across components. -## Testing +## Table of Contents -Please make sure that new utils have unit tests where appropriate. +* [arraysAreEqual](./arrays-are-equal) +* [isEmpty / notEmpty](./isEmpty) +* [registerComponent](./register-component) diff --git a/src/utils/register-component/index.ts b/src/utils/register-component/index.ts new file mode 100644 index 0000000000..7202607313 --- /dev/null +++ b/src/utils/register-component/index.ts @@ -0,0 +1,4 @@ +import registerComponent from './register-component'; + +export { registerComponent }; +export default registerComponent; diff --git a/src/utils/register-component/readme.md b/src/utils/register-component/readme.md new file mode 100644 index 0000000000..25a547b449 --- /dev/null +++ b/src/utils/register-component/readme.md @@ -0,0 +1,13 @@ +# `registerComponent` +Registers a component into the global Vue context. + +## Usage +```js +registerComponent('v-button', VButton); +``` + +## Vue.component() vs registerComponent() +`registerComponent` internally calls `Vue.component()` directly, and doesn't do anything else. The +function is purely to extend the accepted TypeScript type for the second parameter. Vue accepts the +second parameter to be of type `Component`, yet it's `Vue.component()` function doesn't actually have +that type in it's definition. diff --git a/src/utils/register-component.test.ts b/src/utils/register-component/register-component.test.ts similarity index 100% rename from src/utils/register-component.test.ts rename to src/utils/register-component/register-component.test.ts diff --git a/src/utils/register-component.ts b/src/utils/register-component/register-component.ts similarity index 100% rename from src/utils/register-component.ts rename to src/utils/register-component/register-component.ts diff --git a/src/views/private-view/drawer-detail/drawer-detail.test.ts b/src/views/private-view/drawer-detail/drawer-detail.test.ts index 6e57e2da4f..e774d33c1e 100644 --- a/src/views/private-view/drawer-detail/drawer-detail.test.ts +++ b/src/views/private-view/drawer-detail/drawer-detail.test.ts @@ -1,7 +1,7 @@ import { mount, createLocalVue } from '@vue/test-utils'; import VueCompositionAPI, { ref } from '@vue/composition-api'; import DrawerDetail from './drawer-detail.vue'; -import * as GroupableComposition from '@/compositions/groupable'; +import * as GroupableComposition from '@/compositions/groupable/groupable'; import VIcon from '@/components/v-icon'; const localVue = createLocalVue(); diff --git a/src/views/readme.md b/src/views/readme.md index b55cb08b68..69fa6e2ada 100644 --- a/src/views/readme.md +++ b/src/views/readme.md @@ -1,3 +1,10 @@ # Views -Views are the top-level parent component that are used in all modules. Directus will only have two Views for the foreseeable future: `public` and `private` for non-authenticated and authenticated routes respectively +Views are the top-level parent component that are used in all modules. Directus will only have two +Views for the foreseeable future: `public` and `private` for non-authenticated and authenticated +routes respectively. + +## Table of Contents + +* [Private View](./private-view) +* [Public View](./public)