Merge pull request #272 from directus/show-as-dot

Move color-dot option to labels
This commit is contained in:
Rijk van Zanten
2020-09-17 14:31:35 -04:00
committed by GitHub
10 changed files with 168 additions and 159 deletions

31
app/package-lock.json generated
View File

@@ -3042,11 +3042,32 @@
"@types/tern": "*"
}
},
"@types/color": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.1.tgz",
"integrity": "sha512-oeUWVaAwI+xINDUx+3F2vJkl/vVB03VChFF/Gl3iQCdbcakjuoJyMOba+3BXRtnBhxZ7uBYqQBi9EpLnvSoztA==",
"requires": {
"@types/color-convert": "*"
}
},
"@types/color-convert": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-1.9.0.tgz",
"integrity": "sha512-OKGEfULrvSL2VRbkl/gnjjgbbF7ycIlpSsX7Nkab4MOWi5XxmgBYvuiQ7lcCFY5cPDz7MUNaKgxte2VRmtr4Fg==",
"requires": {
"@types/color-name": "*"
}
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/color-string": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@types/color-string/-/color-string-1.5.0.tgz",
"integrity": "sha512-17/8LWbkfvoKgfnnBvKbUnPTzPtzBlSELf5FPvVt9dRTQW88igOYZZ78us9dmbY1301VtTBEnuPTKspvmtGDxA=="
},
"@types/connect": {
"version": "3.4.33",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
@@ -8533,7 +8554,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz",
"integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==",
"dev": true,
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
@@ -8543,7 +8563,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
@@ -8551,8 +8570,7 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}
}
},
@@ -8573,7 +8591,6 @@
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
"dev": true,
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@@ -23099,7 +23116,6 @@
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"dev": true,
"requires": {
"is-arrayish": "^0.3.1"
},
@@ -23107,8 +23123,7 @@
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"dev": true
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},

View File

@@ -35,6 +35,8 @@
"@sindresorhus/slugify": "^1.0.0",
"@tinymce/tinymce-vue": "^3.2.2",
"@types/codemirror": "^0.0.97",
"@types/color": "^3.0.1",
"@types/color-string": "^1.5.0",
"@types/debug": "^4.1.5",
"@types/htmlhint": "^0.9.1",
"@types/js-yaml": "^3.12.5",
@@ -45,6 +47,8 @@
"base-64": "^0.1.0",
"bytes": "^3.1.0",
"codemirror": "^5.56.0",
"color": "^3.1.2",
"color-string": "^1.5.3",
"cropperjs": "^1.5.7",
"csslint": "^1.0.5",
"date-fns": "^2.14.0",

View File

@@ -1,74 +0,0 @@
<template>
<div class="color-dot">
<value-null v-if="value === null" />
<div class="dot" :style="styles" v-tooltip="displayValue"></div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, PropType } from '@vue/composition-api';
import formatTitle from '@directus/format-title';
import { isHex } from '@/utils/color';
type Choice = {
value: string;
text: string;
color: string | null;
};
export default defineComponent({
props: {
value: {
type: String,
default: null,
},
choices: {
type: Array as PropType<Choice[]>,
default: () => [],
},
defaultColor: {
type: String,
default: '#B0BEC5',
},
},
setup(props) {
const currentChoice = computed(() => {
return props.choices.find((choice) => {
return choice.value === props.value;
});
});
const displayValue = computed(() => {
return formatTitle(props.value);
});
const styles = computed(() => {
if (isHex(props.value)) {
return { backgroundColor: props.value || props.defaultColor };
}
return {
backgroundColor: currentChoice.value?.color || props.defaultColor,
};
});
return { displayValue, styles, isHex };
},
});
</script>
<style lang="scss" scoped>
.color-dot {
display: flex;
align-items: center;
.dot {
display: inline-block;
flex-shrink: 0;
width: 12px;
height: 12px;
margin: 0 4px;
border-radius: 6px;
}
}
</style>

View File

@@ -1,60 +0,0 @@
import { defineDisplay } from '@/displays/define';
import DisplayColorDot from './color-dot.vue';
export default defineDisplay(({ i18n }) => ({
id: 'color-dot',
name: i18n.t('displays.color-dot.color-dot'),
description: i18n.t('displays.color-dot.description'),
types: ['string'],
icon: 'flag',
handler: DisplayColorDot,
options: [
{
field: 'defaultColor',
name: i18n.t('displays.color-dot.default_color'),
type: 'string',
meta: {
interface: 'color',
width: 'half',
},
schema: {
default_value: '#B0BEC5',
},
},
{
field: 'choices',
name: i18n.t('choices'),
type: 'json',
meta: {
note: i18n.t('displays.color-dot.choices_note'),
interface: 'repeater',
options: {
template: '{{text}}',
fields: [
{
field: 'value',
name: i18n.t('value'),
type: 'string',
meta: {
interface: 'text-input',
options: {
font: 'monospace',
},
width: 'half',
},
},
{
field: 'color',
name: i18n.t('color'),
type: 'string',
meta: {
interface: 'color',
width: 'half',
},
},
],
},
},
},
],
}));

View File

@@ -0,0 +1,68 @@
<template>
<div class="color-dot">
<value-null v-if="value === null" />
<div class="dot" :style="styles"></div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, PropType } from '@vue/composition-api';
import formatTitle from '@directus/format-title';
import Color from 'color';
import colorString from 'color-string';
export default defineComponent({
props: {
value: {
type: String,
default: null,
},
defaultColor: {
type: String,
default: '#B0BEC5',
validator: (value: string) => colorString.get.rgb(value) !== null,
},
},
setup(props) {
const displayValue = computed(() => {
return props.value;
});
const styles = computed(() => {
const style: Record<string, any> = { 'background-color': props.defaultColor };
if (Color(props.value) !== undefined) style['background-color'] = props.value;
const pageColorString = getComputedStyle(document.body).getPropertyValue('--background-page');
const pageColorRGB = colorString.get.rgb(pageColorString) || colorString.get.rgb('#FFF');
const colorRGB = colorString.get.rgb(props.value) || colorString.get.rgb(props.defaultColor);
if (pageColorRGB == null || colorRGB == null) return {};
if (Color.rgb(...colorRGB.slice(0.3)).contrast(Color.rgb(...pageColorRGB.slice(0, 3))) < 3)
style['border'] = '1px solid var(--border-normal-alt)';
return style;
});
return { displayValue, styles };
},
});
</script>
<style lang="scss" scoped>
.color-dot {
display: flex;
align-items: center;
.dot {
display: inline-block;
flex-shrink: 0;
width: 12px;
height: 12px;
margin: 0 4px;
border-radius: 6px;
}
}
</style>

View File

@@ -0,0 +1,25 @@
import { defineDisplay } from '@/displays/define';
import DisplayColor from './color.vue';
export default defineDisplay(({ i18n }) => ({
id: 'color',
name: i18n.t('displays.color.color'),
description: i18n.t('displays.color.description'),
types: ['string'],
icon: 'flag',
handler: DisplayColor,
options: [
{
field: 'defaultColor',
name: i18n.t('displays.color.default_color'),
type: 'string',
meta: {
interface: 'color',
width: 'half',
},
schema: {
default_value: '#B0BEC5',
},
},
],
}));

View File

@@ -38,7 +38,7 @@ export default defineDisplay(({ i18n }) => ({
name: i18n.t('format_text'),
type: 'boolean',
meta: {
width: 'half-left',
width: 'half',
interface: 'toggle',
options: {
label: i18n.t('displays.labels.format_label'),
@@ -48,6 +48,18 @@ export default defineDisplay(({ i18n }) => ({
default_value: true,
},
},
{
field: 'showAsDot',
name: i18n.t('displays.labels.show_as_dot'),
type: 'boolean',
meta: {
width: 'half',
interface: 'toggle',
},
schema: {
default_value: false,
},
},
{
field: 'choices',
name: i18n.t('choices'),

View File

@@ -1,18 +1,29 @@
<template>
<div class="display-tags">
<v-chip
v-for="item in items"
:key="item.value"
:style="{
'--v-chip-color': item.foreground,
'--v-chip-background-color': item.background,
}"
small
disabled
label
>
{{ item.text }}
</v-chip>
<template v-if="!showAsDot">
<v-chip
v-for="item in items"
:key="item.value"
:style="{
'--v-chip-color': item.foreground,
'--v-chip-background-color': item.background,
}"
small
disabled
label
>
{{ item.text }}
</v-chip>
</template>
<template v-else>
<display-color
v-for="item in items"
:key="item.value"
:value="item.background"
:default-color="defaultBackground"
v-tooltip="item.text"
/>
</template>
</div>
</template>
@@ -37,6 +48,10 @@ export default defineComponent({
type: Boolean,
default: true,
},
showAsDot: {
type: Boolean,
default: false
},
choices: {
type: Array as PropType<Choice[]>,
default: () => [],
@@ -51,7 +66,7 @@ export default defineComponent({
},
type: {
type: String,
validator: (val: string) => ['json', 'string'].includes(val),
validator: (val: string) => ['text', 'string'].includes(val),
},
},
setup(props) {
@@ -90,7 +105,7 @@ export default defineComponent({
<style lang="scss" scoped>
.display-tags {
display: inline-block;
display: flex;
}
.v-chip + .v-chip {

View File

@@ -90,6 +90,10 @@
"name": "Name",
"both": "Both",
"circle_label": "Show user in a circle"
},
"labels": {
"labels": "Labels",
"show_as_dot": "Show as dot"
}
}
}

View File

@@ -16,7 +16,7 @@
--background-highlight: #F9FAFB; // ADJUST
--background-page: #263238;
--background-page-rgb: 38, 50, 56;
--background-inverted: #fff;
--background-inverted: #FFF;
--overlay-color: rgba(19, 24, 26, 0.9);