TS Errors part 5 (#18507)

* Datetime interface

* Couple more errors

* list/

* Map

* Presentation links

* Select dropdown

* Select multiple

* Select radio

* Translations

* Calendar layout

* Cards layout

* Map layout
This commit is contained in:
Rijk van Zanten
2023-05-05 16:10:21 -04:00
committed by GitHub
parent d633e11631
commit 776682fc06
20 changed files with 90 additions and 80 deletions

View File

@@ -83,19 +83,19 @@
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { computed, ref, toRefs } from 'vue';
import { Field } from '@directus/types';
import Draggable from 'vuedraggable';
import { i18n } from '@/lang';
import { renderStringTemplate } from '@/utils/render-string-template';
import formatTitle from '@directus/format-title';
import { DeepPartial, Field, FieldMeta } from '@directus/types';
import { isEqual, sortBy } from 'lodash';
import { computed, ref, toRefs } from 'vue';
import { useI18n } from 'vue-i18n';
import Draggable from 'vuedraggable';
const props = withDefaults(
defineProps<{
value: Record<string, unknown>[] | null;
fields?: Partial<Field>[];
fields?: DeepPartial<Field>[];
template?: string;
addLabel?: string;
sort?: string;
@@ -115,7 +115,7 @@ const props = withDefaults(
);
const emit = defineEmits<{
(e: 'input', value: Record<string, unknown>[] | null): void;
(e: 'input', value: FieldMeta[] | null): void;
}>();
const { t } = useI18n();

View File

@@ -50,7 +50,7 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
(e: 'input', value: Record<string, any>[] | null): void;
(e: 'input', value: Record<string, any> | null): void;
}>();
const { t } = useI18n();

View File

@@ -1,4 +1,5 @@
import { defineInterface } from '@directus/utils';
import type { ComponentOptions } from 'vue';
import InterfaceMap from './map.vue';
import Options from './options.vue';
import PreviewSVG from './preview.svg?raw';
@@ -23,7 +24,7 @@ export default defineInterface({
'csv',
],
group: 'selection',
options: Options,
options: Options as ComponentOptions,
recommendedDisplays: [],
preview: PreviewSVG,
});

View File

@@ -13,7 +13,7 @@
<div
v-if="location"
class="mapboxgl-user-location-dot mapboxgl-search-location-dot"
:style="`transform: translate(${projection.x}px, ${projection.y}px) translate(-50%, -50%) rotateX(0deg) rotateZ(0deg)`"
:style="`transform: translate(${projection!.x}px, ${projection!.y}px) translate(-50%, -50%) rotateX(0deg) rotateZ(0deg)`"
></div>
<transition name="fade">
<div
@@ -62,8 +62,18 @@
</template>
<script setup lang="ts">
import { useAppStore } from '@/stores/app';
import { useSettingsStore } from '@/stores/settings';
import { flatten, getBBox, getGeometryFormatForType, getParser, getSerializer } from '@/utils/geometry';
import { getBasemapSources, getStyleFromBasemapSource } from '@/utils/geometry/basemap';
import { ButtonControl } from '@/utils/geometry/controls';
import { Field, GeoJSONParser, GeoJSONSerializer, GeometryType, MultiGeometry, SimpleGeometry } from '@directus/types';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
import { Geometry } from 'geojson';
import { debounce, isEqual, snakeCase } from 'lodash';
import maplibre, {
AnimationOptions,
AttributionControl,
@@ -75,21 +85,13 @@ import maplibre, {
NavigationControl,
} from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import type { Ref } from 'vue';
import { computed, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';
import { useSettingsStore } from '@/stores/settings';
import { flatten, getBBox, getGeometryFormatForType, getParser, getSerializer } from '@/utils/geometry';
import { ButtonControl } from '@/utils/geometry/controls';
import { Field, GeoJSONParser, GeoJSONSerializer, GeometryType, MultiGeometry, SimpleGeometry } from '@directus/types';
import { TranslateResult, useI18n } from 'vue-i18n';
import { getMapStyle } from './style';
// @ts-ignore
import StaticMode from '@mapbox/mapbox-gl-draw-static-mode';
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
import { Geometry } from 'geojson';
import { debounce, isEqual, snakeCase } from 'lodash';
import { getMapStyle } from './style';
import { useAppStore } from '@/stores/app';
import { TranslateResult, useI18n } from 'vue-i18n';
import { getBasemapSources, getStyleFromBasemapSource } from '@/utils/geometry/basemap';
const activeLayers = [
'directus-point',
@@ -121,7 +123,7 @@ const emit = defineEmits<{
}>();
const { t } = useI18n();
const container = ref<HTMLElement | null>(null);
const container: Ref<HTMLElement | null> = ref(null);
let map: Map;
let mapLoading = ref(true);
let currentGeometry: Geometry | null | undefined;
@@ -291,7 +293,7 @@ function updateValue(value: any) {
controls.draw.changeMode(mode);
}
} else {
if (!isEqual(value, currentGeometry && serialize(currentGeometry))) {
if (!isEqual(value, currentGeometry && serialize(currentGeometry as any))) {
loadValueFromProps();
controls.draw.changeMode('simple_select');
}
@@ -449,7 +451,7 @@ function handleDrawUpdate() {
controls.draw.deleteAll();
emit('input', null);
} else {
emit('input', serialize(currentGeometry));
emit('input', serialize(currentGeometry as any));
}
}

View File

@@ -24,6 +24,7 @@ import { GEOMETRY_TYPES } from '@directus/constants';
import { Field, GeometryOptions, GeometryType } from '@directus/types';
import { CameraOptions, Map } from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import type { Ref } from 'vue';
import { computed, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -62,7 +63,7 @@ function input() {
});
}
const mapContainer = ref<HTMLElement | null>(null);
const mapContainer: Ref<HTMLElement | null> = ref(null);
let map: Map;
const mapboxKey = settingsStore.settings?.mapbox_key;

View File

@@ -17,14 +17,14 @@
</template>
<script setup lang="ts">
import { computed, inject, ref, toRefs } from 'vue';
import { render } from 'micromustache';
import { omit } from 'lodash';
import { useItem } from '@/composables/use-item';
import { getFieldsFromTemplate } from '@directus/utils';
import { Query } from '@directus/types';
import { useCollection } from '@directus/composables';
import { RELATIONAL_TYPES } from '@directus/constants';
import { Query } from '@directus/types';
import { getFieldsFromTemplate } from '@directus/utils';
import { omit } from 'lodash';
import { render } from 'micromustache';
import { computed, inject, ref, toRefs } from 'vue';
type Link = {
icon: string;
@@ -66,7 +66,11 @@ const fullItem = computed(() => {
const itemValue = item.value ?? {};
for (const field of fields.value) {
if (field.meta?.special?.some((special) => RELATIONAL_TYPES.includes(special))) continue;
if (
field.meta?.special?.some((special) => RELATIONAL_TYPES.includes(special as (typeof RELATIONAL_TYPES)[number]))
) {
continue;
}
itemValue[field.field] = values.value[field.field];
}

View File

@@ -1,6 +1,6 @@
import { defineInterface } from '@directus/utils';
import InterfaceSelectDropdownM2O from './select-dropdown-m2o.vue';
import PreviewSVG from './preview.svg?raw';
import InterfaceSelectDropdownM2O from './select-dropdown-m2o.vue';
export default defineInterface({
id: 'select-dropdown-m2o',
@@ -30,7 +30,7 @@ export default defineInterface({
field: 'enableCreate',
name: '$t:creating_items',
schema: {
default_value: true,
default_value: 'true',
},
meta: {
interface: 'boolean',
@@ -44,7 +44,7 @@ export default defineInterface({
field: 'enableSelect',
name: '$t:selecting_items',
schema: {
default_value: true,
default_value: 'true',
},
meta: {
interface: 'boolean',

View File

@@ -76,8 +76,9 @@
</template>
<script setup lang="ts">
import { RelationQuerySingle, useRelationSingle } from '@/composables/use-relation-single';
import { useRelationM2O } from '@/composables/use-relation-m2o';
import { useRelationPermissionsM2O } from '@/composables/use-relation-permissions';
import { RelationQuerySingle, useRelationSingle } from '@/composables/use-relation-single';
import { useCollectionsStore } from '@/stores/collections';
import { adjustFieldsForDisplays } from '@/utils/adjust-fields-for-displays';
import { parseFilter } from '@/utils/parse-filter';
@@ -89,7 +90,6 @@ import { get } from 'lodash';
import { render } from 'micromustache';
import { computed, inject, ref, toRefs } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRelationPermissionsM2O } from '@/composables/use-relation-permissions';
const props = withDefaults(
defineProps<{
@@ -220,11 +220,11 @@ const selection = computed<(number | string)[]>(() => {
return [props.value];
});
function onSelection(selection: (number | string)[]) {
if (selection.length === 0) {
function onSelection(selection: (number | string)[] | null) {
if (selection!.length === 0) {
remove();
} else {
update(selection[0]);
update(selection![0]);
}
selectModalActive.value = false;

View File

@@ -1,6 +1,6 @@
import { defineInterface } from '@directus/utils';
import InterfaceSelectDropdown from './select-dropdown.vue';
import PreviewSVG from './preview.svg?raw';
import InterfaceSelectDropdown from './select-dropdown.vue';
export default defineInterface({
id: 'select-dropdown',
@@ -66,7 +66,7 @@ export default defineInterface({
},
},
schema: {
default_value: false,
default_value: 'false',
},
},
{
@@ -81,7 +81,7 @@ export default defineInterface({
},
},
schema: {
default_value: false,
default_value: 'false',
},
},
{

View File

@@ -73,9 +73,9 @@ type Option = {
const props = withDefaults(
defineProps<{
value?: string[];
value: string[] | null;
disabled?: boolean;
choices?: Option[];
choices: Option[];
allowOther?: boolean;
width?: string;
iconOn?: string;
@@ -98,17 +98,17 @@ const { t } = useI18n();
const { choices, value } = toRefs(props);
const showAll = ref(false);
const hideChoices = computed(() => props.choices.length > props.itemsShown);
const hideChoices = computed(() => props.choices!.length > props.itemsShown);
const choicesDisplayed = computed(() => {
if (showAll.value || hideChoices.value === false) {
return props.choices;
}
return props.choices.slice(0, props.itemsShown);
return props.choices!.slice(0, props.itemsShown);
});
const hiddenCount = computed(() => props.choices.length - props.itemsShown);
const hiddenCount = computed(() => props.choices!.length - props.itemsShown);
const gridClass = computed(() => {
if (choices?.value === undefined) return null;

View File

@@ -53,7 +53,7 @@ const { t } = useI18n();
function updateValue(value: string[]) {
const sortedValue = sortBy(value, (val) => {
const sortIndex = props.choices.findIndex((choice) => val === choice.value);
const sortIndex = props.choices!.findIndex((choice) => val === choice.value);
return sortIndex !== -1 ? sortIndex : value.length;
});

View File

@@ -1,6 +1,6 @@
import { defineInterface } from '@directus/utils';
import InterfaceSelectRadio from './select-radio.vue';
import PreviewSVG from './preview.svg?raw';
import InterfaceSelectRadio from './select-radio.vue';
export default defineInterface({
id: 'select-radio',
@@ -95,7 +95,7 @@ export default defineInterface({
},
},
schema: {
default_value: false,
default_value: 'false',
},
},
],

View File

@@ -92,7 +92,9 @@ const gridClass = computed(() => {
return 'grid-1';
});
const { otherValue, usesOtherValue } = useCustomSelection(value, choices, (value) => emit('input', value));
const { otherValue, usesOtherValue } = useCustomSelection(value as any, choices as any, (value) =>
emit('input', value)
);
const customIcon = computed(() => {
if (!otherValue.value) return 'add';

View File

@@ -1,7 +1,7 @@
import { defineInterface } from '@directus/utils';
import InterfaceTranslations from './translations.vue';
import { useFieldsStore } from '@/stores/fields';
import { defineInterface } from '@directus/utils';
import PreviewSVG from './preview.svg?raw';
import InterfaceTranslations from './translations.vue';
export default defineInterface({
id: 'translations',
@@ -70,7 +70,7 @@ export default defineInterface({
name: '$t:interfaces.translations.user_language',
type: 'string',
schema: {
default_value: false,
default_value: 'false',
},
meta: {
interface: 'boolean',

View File

@@ -9,13 +9,13 @@ import { unexpectedError } from '@/utils/unexpected-error';
import { useCollection, useItems, useSync } from '@directus/composables';
import { Field, Item } from '@directus/types';
import { defineLayout, getEndpoint, getFieldsFromTemplate } from '@directus/utils';
import { Calendar, CalendarOptions as FullCalendarOptions, EventInput } from '@fullcalendar/core';
import { Calendar, EventInput, CalendarOptions as FullCalendarOptions } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import listPlugin from '@fullcalendar/list';
import timeGridPlugin from '@fullcalendar/timegrid';
import { format, formatISO, isValid, parse } from 'date-fns';
import { computed, ref, Ref, toRefs, watch } from 'vue';
import { Ref, computed, ref, toRefs, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import CalendarActions from './actions.vue';
import CalendarLayout from './calendar.vue';
@@ -316,7 +316,7 @@ export default defineLayout<LayoutOptions>({
id: primaryKey,
title:
renderDisplayStringTemplate(
collection.value,
collection.value!,
template.value || `{{ ${primaryKeyField.value.field} }}`,
item
) || item[primaryKeyField.value.field],

View File

@@ -1,6 +1,6 @@
<template>
<div ref="layoutElement" class="layout-cards" :style="{ '--size': size * 40 + 'px' }">
<template v-if="loading || itemCount > 0">
<template v-if="loading || itemCount! > 0">
<cards-header
v-model:size="sizeWritable"
v-model:selection="selectionWritable"
@@ -13,9 +13,9 @@
<div class="grid" :class="{ 'single-row': isSingleRow }">
<card
v-for="item in items"
:key="item[primaryKeyField.field]"
:key="item[primaryKeyField!.field]"
v-model="selectionWritable"
:item-key="primaryKeyField.field"
:item-key="primaryKeyField!.field"
:crop="imageFit === 'crop'"
:icon="icon"
:file="imageSource ? item[imageSource] : null"
@@ -93,7 +93,7 @@ const props = withDefaults(
defineProps<{
collection: string;
items: Item[];
selection: Item[];
selection: (number | string)[];
selectMode: boolean;
readonly: boolean;
limit: number;
@@ -106,7 +106,7 @@ const props = withDefaults(
page: number;
toPage: (newPage: number) => void;
getLinkForItem: (item: Record<string, any>) => string | undefined;
fieldsInCollection: Item[];
fieldsInCollection: Field[];
selectAll: () => void;
resetPresetAndRefresh: () => Promise<void>;
sort: string[];
@@ -144,7 +144,7 @@ const { width } = useElementSize(layoutElement);
watch(
() => props.page,
() => mainElement.value?.scrollTo({ top: 0, behavior: 'smooth' })
() => mainElement!.value?.scrollTo({ top: 0, behavior: 'smooth' })
);
watch(width, () => {

View File

@@ -151,7 +151,7 @@ function setupMap() {
map.on('select.enable', () => (selectMode.value = true));
map.on('select.disable', () => (selectMode.value = false));
map.on('select.end', (event: MapLayerMouseEvent) => {
map.on('select.end', (event: MapLayerMouseEvent & { alt: unknown }) => {
const ids = event.features?.map((f) => f.id);
emit('featureselect', { ids, replace: !event.alt });
});

View File

@@ -1,7 +1,9 @@
import { formatCollectionItemsCount } from '@/utils/format-collection-items-count';
import { getGeometryFormatForType, toGeoJSON } from '@/utils/geometry';
import { saveAsCSV } from '@/utils/save-as-csv';
import { syncRefProperty } from '@/utils/sync-ref-property';
import { useCollection, useItems, useSync } from '@directus/composables';
import { Field, Filter, GeometryOptions, Item } from '@directus/types';
import { Field, Filter, GeometryOptions } from '@directus/types';
import { defineLayout, getFieldsFromTemplate } from '@directus/utils';
import { cloneDeep, merge } from 'lodash';
import { computed, ref, toRefs, watch } from 'vue';
@@ -11,8 +13,6 @@ import MapLayout from './map.vue';
import MapOptions from './options.vue';
import { getMapStyle } from './style';
import { LayoutOptions, LayoutQuery } from './types';
import { formatCollectionItemsCount } from '@/utils/format-collection-items-count';
import { saveAsCSV } from '@/utils/save-as-csv';
export default defineLayout<LayoutOptions, LayoutQuery>({
id: 'map',
@@ -211,20 +211,20 @@ export default defineLayout<LayoutOptions, LayoutQuery>({
});
}
function setSelection(ids: Item[]) {
function setSelection(ids: (string | number)[]) {
selection.value = Array.from(new Set(ids));
}
function pushSelection(ids: Item[]) {
function pushSelection(ids: (string | number)[]) {
selection.value = Array.from(new Set(selection.value.concat(ids)));
}
function handleSelect({ ids, replace }: { ids: Item[]; replace: boolean }) {
function handleSelect({ ids, replace }: { ids: (string | number)[]; replace: boolean }) {
if (replace) setSelection(ids);
else pushSelection(ids);
}
function handleClick({ id, replace }: { id: Item; replace: boolean }) {
function handleClick({ id, replace }: { id: string | number; replace: boolean }) {
if (props.selectMode) {
handleSelect({ ids: [id], replace });
} else {

View File

@@ -20,11 +20,11 @@
<transition name="fade">
<div
v-if="itemPopup.item"
v-if="itemPopup!.item"
class="popup"
:style="{ top: itemPopup.position.y + 'px', left: itemPopup.position.x + 'px' }"
:style="{ top: itemPopup!.position!.y + 'px', left: itemPopup!.position!.x + 'px' }"
>
<render-template :template="template" :item="itemPopup.item" :collection="collection" />
<render-template :template="template" :item="itemPopup!.item" :collection="collection" />
</div>
</transition>
@@ -50,7 +50,7 @@
<v-progress-circular v-else-if="loading || geojsonLoading" indeterminate x-large class="center" />
</transition>
<template v-if="loading || itemCount > 0">
<template v-if="loading || itemCount! > 0">
<div class="footer">
<div v-if="totalPages > 1" class="pagination">
<v-pagination
@@ -99,10 +99,10 @@ export default {
</script>
<script setup lang="ts">
import { useSync } from '@directus/composables';
import { GeometryOptions } from '@directus/types';
import { useI18n } from 'vue-i18n';
import MapComponent from './components/map.vue';
import { useSync } from '@directus/composables';
import { GeometryOptions, Item } from '@directus/types';
const props = withDefaults(
defineProps<{
@@ -121,7 +121,7 @@ const props = withDefaults(
page: number;
toPage: (newPage: number) => void;
limit: number;
selection?: Item[];
selection?: (string | number)[];
error?: any;
geojsonError?: string;
geometryOptions?: GeometryOptions;

View File

@@ -8,7 +8,7 @@ export type UsableCustomSelection = {
};
export function useCustomSelection(
currentValue: Ref<string>,
currentValue: Ref<string | null>,
items: Ref<any[]>,
emit: (event: string | null) => void
): UsableCustomSelection {
@@ -54,7 +54,7 @@ type UsableCustomSelectionMultiple = {
};
export function useCustomSelectionMultiple(
currentValues: Ref<string[]>,
currentValues: Ref<string[] | null>,
items: Ref<any[]>,
emit: (event: string[] | null) => void
): UsableCustomSelectionMultiple {