From 41d77cde652ca47e8fe08be16dce3c98f9df64b4 Mon Sep 17 00:00:00 2001 From: Rijk van Zanten Date: Fri, 24 Apr 2020 15:31:06 -0400 Subject: [PATCH] Status interface (#471) * Add status interface * Add some tests * Set active state of list item and add disabled --- src/interfaces/index.ts | 2 + src/interfaces/status/index.ts | 17 +++++ src/interfaces/status/readme.md | 26 ++++++++ src/interfaces/status/status.story.ts | 55 ++++++++++++++++ src/interfaces/status/status.test.ts | 66 ++++++++++++++++++++ src/interfaces/status/status.vue | 90 +++++++++++++++++++++++++++ src/lang/en-US/index.json | 5 ++ 7 files changed, 261 insertions(+) create mode 100644 src/interfaces/status/index.ts create mode 100644 src/interfaces/status/readme.md create mode 100644 src/interfaces/status/status.story.ts create mode 100644 src/interfaces/status/status.test.ts create mode 100644 src/interfaces/status/status.vue diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 06d246c01a..b94e96c7de 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -9,6 +9,7 @@ import InterfaceDropdown from './dropdown/'; import InterfaceDropdownMultiselect from './dropdown-multiselect/'; import InterfaceRadioButtons from './radio-buttons'; import InterfaceCheckboxes from './checkboxes'; +import InterfaceStatus from './status'; export const interfaces = [ InterfaceTextInput, @@ -22,6 +23,7 @@ export const interfaces = [ InterfaceDropdownMultiselect, InterfaceRadioButtons, InterfaceCheckboxes, + InterfaceStatus, ]; export default interfaces; diff --git a/src/interfaces/status/index.ts b/src/interfaces/status/index.ts new file mode 100644 index 0000000000..ae52f77502 --- /dev/null +++ b/src/interfaces/status/index.ts @@ -0,0 +1,17 @@ +import InterfaceStatus from './status.vue'; +import { defineInterface } from '@/interfaces/define'; + +export default defineInterface(({ i18n }) => ({ + id: 'status', + name: i18n.t('status'), + icon: 'bubble_chart', + component: InterfaceStatus, + options: [ + { + field: 'status_mapping', + name: i18n.t('status_mapping'), + width: 'full', + interface: 'code', + }, + ], +})); diff --git a/src/interfaces/status/readme.md b/src/interfaces/status/readme.md new file mode 100644 index 0000000000..93246c30ca --- /dev/null +++ b/src/interfaces/status/readme.md @@ -0,0 +1,26 @@ +# Status Interface + +Renders a dropdown with the available status options. + +## Options + +| Option | Description | Default | +|------------------|-----------------------------|---------| +| `status_mapping` | What statuses are available | `null` | + +### Status Mapping format + +```ts +type Status = { + [key: string]: { + name: string; + text_color: string; + background_color: string; + soft_delete: boolean; + published: boolean; + } +} +``` + +`status_mapping` is the only option for an interface that isn't camelCased. This is due to the fact +that the API relies on the same setting for it's permissions management. diff --git a/src/interfaces/status/status.story.ts b/src/interfaces/status/status.story.ts new file mode 100644 index 0000000000..c5d96f2b9f --- /dev/null +++ b/src/interfaces/status/status.story.ts @@ -0,0 +1,55 @@ +import withPadding from '../../../.storybook/decorators/with-padding'; +import { defineComponent, ref } from '@vue/composition-api'; +import { boolean, withKnobs, object } from '@storybook/addon-knobs'; +import readme from './readme.md'; +import RawValue from '../../../.storybook/raw-value.vue'; +import i18n from '@/lang'; + +export default { + title: 'Interfaces / Status', + decorators: [withPadding, withKnobs], + parameters: { + notes: readme, + }, +}; + +export const basic = () => + defineComponent({ + i18n, + components: { RawValue }, + props: { + statusMapping: { + default: object('Status Mapping', { + published: { + name: 'Published', + background_color: 'var(--primary)', + }, + draft: { + name: 'Draft', + background_color: 'var(--background-normal)', + }, + deleted: { + name: 'Deleted', + background_color: 'var(--danger)', + }, + }), + }, + disabled: { + default: boolean('Disabled', false), + }, + }, + setup() { + const value = ref(null); + return { value }; + }, + template: ` +
+ + {{ value }} +
+ `, + }); diff --git a/src/interfaces/status/status.test.ts b/src/interfaces/status/status.test.ts new file mode 100644 index 0000000000..0cad08cedc --- /dev/null +++ b/src/interfaces/status/status.test.ts @@ -0,0 +1,66 @@ +import VueCompositionAPI from '@vue/composition-api'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import InterfaceStatus from './status.vue'; +import VNotice from '@/components/v-notice'; +import VMenu from '@/components/v-menu'; +import VList, { VListItem, VListItemIcon, VListItemContent } from '@/components/v-list'; +import i18n from '@/lang'; + +const localVue = createLocalVue(); +localVue.use(VueCompositionAPI); +localVue.component('v-notice', VNotice); +localVue.component('v-menu', VMenu); +localVue.component('v-list', VList); +localVue.component('v-list-item', VListItem); +localVue.component('v-list-item-content', VListItemContent); +localVue.component('v-list-item-icon', VListItemIcon); + +describe('Interfaces / Slider', () => { + it('Renders a notice when status mapping is missing', () => { + const component = shallowMount(InterfaceStatus, { + localVue, + i18n, + propsData: {}, + }); + + expect(component.find(VNotice).exists()).toBe(true); + }); + + it('Converts the status mapping into a loopable array', () => { + const component = shallowMount(InterfaceStatus, { + localVue, + i18n, + propsData: { + status_mapping: null, + }, + }); + + expect((component.vm as any).statuses).toBe(null); + + component.setProps({ + status_mapping: { + test: { + name: 'Test', + background_color: '#abcabc', + }, + another_test: { + name: 'Another Test', + background_color: '#123123', + }, + }, + }); + + expect((component.vm as any).statuses).toEqual([ + { + value: 'test', + name: 'Test', + color: '#abcabc', + }, + { + value: 'another_test', + name: 'Another Test', + color: '#123123', + }, + ]); + }); +}); diff --git a/src/interfaces/status/status.vue b/src/interfaces/status/status.vue new file mode 100644 index 0000000000..a8d5ddaf6a --- /dev/null +++ b/src/interfaces/status/status.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/lang/en-US/index.json b/src/lang/en-US/index.json index 73ac6a7aaa..8adb7fdd09 100644 --- a/src/lang/en-US/index.json +++ b/src/lang/en-US/index.json @@ -122,6 +122,8 @@ "radio_buttons": "Radio Buttons", "checkboxes": "Checkboxes", + "choose_status": "Choose Status...", + "users": "Users", "files": "Files", "activity": "Activity", @@ -351,6 +353,9 @@ "other": "Other...", + "statuses_not_configured": "Status mapping option configured incorrectly", + "status_mapping": "Status Mapping", + "about_directus": "About Directus", "activity_log": "Activity Log", "add_field_filter": "Add a field filter",