Add the cards layout (#430)

* Fix reactivity of currentLayout in drawer detail

* Start on cards layout

* Use dense list items in v-select

* Add cards + size option

* Render cards + files based on options

* Allow modules to set view defaults

* Start on render-template component

* Add get fields from template util

* Use render template component in cards layout

* Render as small icon

* Accept options in display handler function

* Fix type warnings in format title display

* Remove empty styling in render template component

* Account for null values in render template

* Add loading state to cards layout

* Remove type validation in skeleton loader

* Only fetch rendered fields

* Fix resolving of default values for cards module

* Add selection state to cards

* Add selection state to cards

* Make render template reactive

* Implement setup options

* Add disabled support to v-select

* Add fallback icon option + disable fit input when no source

* Add sort header to cards layout

* Remove console log

* Add selection state to cards header

* Fix z-indexing of header menu

* Add pagination to cards layout

* Fix types in field

* Fix type checks in field-setup

* Add role presentation to img

* Remove code smell

* Handle file library gracefully

* Add native lazy loading to images in cards layout

* Render SVGs inline in card
This commit is contained in:
Rijk van Zanten
2020-04-18 16:20:00 -04:00
committed by GitHub
parent 57bb18b590
commit 3a89dc41f9
29 changed files with 1068 additions and 74 deletions

View File

@@ -16,13 +16,15 @@ export default defineComponent({
},
},
setup(props, { emit }) {
let currentLayout = layouts.find((layout) => layout.id === props.value);
const currentLayout = computed(() => {
const layout = layouts.find((layout) => layout.id === props.value);
// If for whatever reason the current layout doesn't exist, force reset it to tabular
if (currentLayout === undefined) {
currentLayout = layouts.find((layout) => layout.id === 'tabular');
emit('input', 'tabular');
}
if (layout === undefined) {
return layouts.find((layout) => layout.id === 'tabular');
}
return layout;
});
const viewType = computed({
get() {

View File

@@ -0,0 +1,4 @@
import RenderTemplate from './render-template.vue';
export { RenderTemplate };
export default RenderTemplate;

View File

@@ -0,0 +1,90 @@
<template>
<div class="render-template">
<template v-for="(part, index) in parts">
<component
v-if="part !== null && typeof part === 'object'"
:is="`display-${part.component}`"
:key="index"
:value="part.value"
v-bind="part.options"
/>
<template v-else>{{ part }}</template>
</template>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, computed } from '@vue/composition-api';
import useFieldsStore from '@/stores/fields';
import { get } from 'lodash';
import { Field } from '@/stores/fields/types';
import displays from '@/displays';
export default defineComponent({
props: {
collection: {
type: String,
required: true,
},
item: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type: Object as PropType<Record<string, any>>,
required: true,
},
template: {
type: String,
required: true,
},
},
setup(props) {
const fieldsStore = useFieldsStore();
const regex = /({{.*?}})/g;
const parts = computed(() =>
props.template.split(regex).map((part) => {
if (part.startsWith('{{') === false) return part;
const fieldKey = part.replace(/{{/g, '').replace(/}}/g, '').trim();
const field: Field | null = fieldsStore.getField(props.collection, fieldKey);
// Instead of crashing when the field doesn't exist, we'll render a couple question
// marks to indicate it's absence
if (!field) return '???';
// Try getting the value from the item, return some question marks if it doesn't exist
const value = get(props.item, fieldKey);
if (value === undefined) return '???';
// If no display is configured, we can render the raw value
if (field.display === null) return value;
const displayInfo = displays.find((display) => display.id === field.display);
// If used display doesn't exist in the current project, return raw value
if (!displayInfo) return value;
// If the display handler is a function, we parse the value and return the result
if (typeof displayInfo.handler === 'function') {
const handler = displayInfo.handler as Function;
return handler(value, field.display_options);
}
return {
component: field.display,
options: field.display_options,
value: value,
};
})
);
return { parts };
},
});
</script>
<style lang="scss" scoped>
.render-template {
display: contents;
}
</style>