Fix lint issues, update deps

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2022-09-20 16:53:26 +02:00
parent 86ca52c2cb
commit 151a7e54ae
61 changed files with 1533 additions and 1579 deletions

View File

@@ -8,6 +8,5 @@
border: 2px solid;
z-index: 2;
flex-shrink: 0;
}
}

View File

@@ -62,9 +62,10 @@ const mentionOptions: MentionOptions = {
let popup: any;
return {
onStart: (props: any) => {
onStart: (props: Record<string, any>) => {
component = new VueRenderer(MentionList, {
propsData: props,
props,
editor: props.editor,
});
popup = tippy("body", {

View File

@@ -20,7 +20,7 @@ import { ref, watch } from "vue";
const props = defineProps<{
items: IPerson[];
command: ({ id }: { id: string }) => {};
command: ({ id }: { id: string }) => any;
}>();
// @Prop({ type: Function, required: true }) command!: any;
@@ -31,37 +31,37 @@ watch(props.items, () => {
selectedIndex.value = 0;
});
const onKeyDown = ({ event }: { event: KeyboardEvent }): boolean => {
if (event.key === "ArrowUp") {
upHandler();
return true;
}
// const onKeyDown = ({ event }: { event: KeyboardEvent }): boolean => {
// if (event.key === "ArrowUp") {
// upHandler();
// return true;
// }
if (event.key === "ArrowDown") {
downHandler();
return true;
}
// if (event.key === "ArrowDown") {
// downHandler();
// return true;
// }
if (event.key === "Enter") {
enterHandler();
return true;
}
// if (event.key === "Enter") {
// enterHandler();
// return true;
// }
return false;
};
// return false;
// };
const upHandler = (): void => {
selectedIndex.value =
(selectedIndex.value + props.items.length - 1) % props.items.length;
};
// const upHandler = (): void => {
// selectedIndex.value =
// (selectedIndex.value + props.items.length - 1) % props.items.length;
// };
const downHandler = (): void => {
selectedIndex.value = (selectedIndex.value + 1) % props.items.length;
};
// const downHandler = (): void => {
// selectedIndex.value = (selectedIndex.value + 1) % props.items.length;
// };
const enterHandler = (): void => {
selectItem(selectedIndex.value);
};
// const enterHandler = (): void => {
// selectItem(selectedIndex.value);
// };
const selectItem = (index: number): void => {
const item = props.items[index];

View File

@@ -1,149 +0,0 @@
<template>
<div class="address-autocomplete">
<!-- <o-field expanded>
<o-autocomplete
:data="addressData"
v-model="queryText"
:placeholder="$t('e.g. 10 Rue Jangot')"
field="fullName"
:loading="isFetching"
@typing="fetchAsyncData"
icon="map-marker"
expanded
@select="updateSelected"
v-bind="$attrs"
dir="auto"
>
<template #default="{ option }">
<o-icon :icon="option.poiInfos.poiIcon.icon" />
<b>{{ option.poiInfos.name }}</b
><br />
<small>{{ option.poiInfos.alternativeName }}</small>
</template>
</o-autocomplete>
</o-field>
<o-field
v-if="canDoGeoLocation"
:message="fieldErrors"
:type="{ 'is-danger': fieldErrors.length }"
>
<o-button
type="is-text"
v-if="!gettingLocation"
icon-right="target"
@click="locateMe"
@keyup.enter="locateMe"
>{{ $t("Use my location") }}</o-button
>
<span v-else>{{ $t("Getting location") }}</span>
</o-field> -->
<!--
<div v-if="selected && selected.geom" class="control">
<o-checkbox @input="togglemap" />
<label class="label">{{ $t("Show map") }}</label>
</div>
<div class="map" v-if="showmap && selected && selected.geom">
<map-leaflet
:coords="selected.geom"
:marker="{
text: [selected.poiInfos.name, selected.poiInfos.alternativeName],
icon: selected.poiInfos.poiIcon.icon,
}"
:updateDraggableMarkerCallback="reverseGeoCode"
:options="{ zoom: mapDefaultZoom }"
:readOnly="false"
/>
</div>
-->
</div>
</template>
<script lang="ts">
import { Prop, Watch, Vue } from "vue-property-decorator";
import { Address, IAddress } from "../../types/address.model";
// import AddressAutoCompleteMixin from "@/mixins/AddressAutoCompleteMixin";
// @Component({
// inheritAttrs: false,
// })
export default class AddressAutoComplete extends Vue {
@Prop({ required: false, default: false }) type!: string | false;
@Prop({ required: false, default: true, type: Boolean })
doGeoLocation!: boolean;
addressData: IAddress[] = [];
selected: IAddress = new Address();
initialQueryText = "";
addressModalActive = false;
showmap = false;
get queryText2(): string {
if (this.value !== undefined) {
return new Address(this.value).fullName;
}
return this.initialQueryText;
}
set queryText2(queryText: string) {
this.initialQueryText = queryText;
}
@Watch("value")
updateEditing(): void {
if (!this.value?.id) return;
this.selected = this.value;
}
updateSelected(option: IAddress): void {
if (option == null) return;
this.selected = option;
// this.$emit("input", this.selected);
}
resetPopup(): void {
this.selected = new Address();
}
openNewAddressModal(): void {
this.resetPopup();
this.addressModalActive = true;
}
togglemap(): void {
this.showmap = !this.showmap;
}
get canDoGeoLocation(): boolean {
return this.isSecureContext && this.doGeoLocation;
}
}
</script>
<style lang="scss">
.address-autocomplete {
margin-bottom: 0.75rem;
}
.autocomplete {
.dropdown-menu {
z-index: 2000;
}
.dropdown-item.is-disabled {
opacity: 1 !important;
cursor: auto;
}
}
.read-only {
cursor: pointer;
}
.map {
height: 400px;
width: 100%;
}
</style>

View File

@@ -150,7 +150,7 @@ import RouteName from "../../router/name";
import InlineAddress from "@/components/Address/InlineAddress.vue";
import { computed, inject } from "vue";
import MobilizonTag from "@/components/Tag.vue";
import MobilizonTag from "@/components/TagElement.vue";
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
import Video from "vue-material-design-icons/Video.vue";
import { formatDateTimeForEvent } from "@/utils/datetime";

View File

@@ -84,7 +84,7 @@
</template>
<a
target="_blank"
class="hover:underline"
class="underline"
rel="noopener noreferrer ugc"
:href="event.onlineAddress"
:title="

View File

@@ -130,7 +130,7 @@ import InlineAddress from "@/components/Address/InlineAddress.vue";
import Video from "vue-material-design-icons/Video.vue";
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
import AccountMultiple from "vue-material-design-icons/AccountMultiple.vue";
import Tag from "@/components/Tag.vue";
import Tag from "@/components/TagElement.vue";
withDefaults(
defineProps<{

View File

@@ -301,7 +301,7 @@ import {
organizerAvatarUrl,
organizerDisplayName,
} from "@/types/event.model";
import { displayNameAndUsername, IActor, IPerson } from "@/types/actor";
import { displayNameAndUsername, IPerson } from "@/types/actor";
import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import RouteName from "@/router/name";
import { changeIdentity } from "@/utils/identity";
@@ -323,29 +323,12 @@ import { useI18n } from "vue-i18n";
import { Dialog } from "@/plugins/dialog";
import { Snackbar } from "@/plugins/snackbar";
import { useDeleteEvent } from "@/composition/apollo/event";
import Tag from "@/components/Tag.vue";
import Tag from "@/components/TagElement.vue";
const defaultOptions: IEventCardOptions = {
hideDate: true,
loggedPerson: false,
hideDetails: false,
organizerActor: null,
};
const props = withDefaults(
defineProps<{
participation: IParticipant;
options?: IEventCardOptions;
}>(),
{
options: () => ({
hideDate: true,
loggedPerson: false,
hideDetails: false,
organizerActor: null,
}),
}
);
const props = defineProps<{
participation: IParticipant;
options?: IEventCardOptions;
}>();
const emit = defineEmits(["eventDeleted"]);
@@ -353,10 +336,6 @@ const { result: currentActorResult } = useQuery(CURRENT_ACTOR_CLIENT);
const currentActor = computed(() => currentActorResult.value?.currentActor);
const { t } = useI18n({ useScope: "global" });
const mergedOptions = computed<IEventCardOptions>(() => {
return { ...defaultOptions, ...props.options };
});
const dialog = inject<Dialog>("dialog");
const openDeleteEventModal = (
@@ -441,9 +420,8 @@ onDeleteEventError((error) => {
* Delete the event
*/
const openDeleteEventModalWrapper = () => {
openDeleteEventModal(
props.participation.event,
deleteEvent(props.participation.event)
openDeleteEventModal(props.participation.event, (event: IEvent) =>
deleteEvent({ eventId: event.id ?? "" })
);
};
@@ -474,15 +452,15 @@ const gotToWithCheck = async (
return router.push(route);
};
const organizerActor = computed<IActor | undefined>(() => {
if (
props.participation.event.attributedTo &&
props.participation.event.attributedTo.id
) {
return props.participation.event.attributedTo;
}
return props.participation.event.organizerActor;
});
// const organizerActor = computed<IActor | undefined>(() => {
// if (
// props.participation.event.attributedTo &&
// props.participation.event.attributedTo.id
// ) {
// return props.participation.event.attributedTo;
// }
// return props.participation.event.organizerActor;
// });
const seatsLeft = computed<number | null>(() => {
if (props.participation.event.options.maximumAttendeeCapacity > 0) {

View File

@@ -143,7 +143,7 @@ const props = withDefaults(
}
);
const addressModalActive = ref(false);
// const addressModalActive = ref(false);
const componentId = 0;
@@ -186,14 +186,14 @@ const updateSelected = (option: IAddress): void => {
emit("update:modelValue", selected.value);
};
const resetPopup = (): void => {
selected.value = new Address();
};
// const resetPopup = (): void => {
// selected.value = new Address();
// };
const openNewAddressModal = (): void => {
resetPopup();
addressModalActive.value = true;
};
// const openNewAddressModal = (): void => {
// resetPopup();
// addressModalActive.value = true;
// };
const checkCurrentPosition = (e: LatLng): boolean => {
if (!selected.value?.geom) return false;

View File

@@ -94,7 +94,7 @@ import ExitToApp from "vue-material-design-icons/ExitToApp.vue";
import DotsHorizontal from "vue-material-design-icons/DotsHorizontal.vue";
import AccountGroup from "vue-material-design-icons/AccountGroup.vue";
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
import Tag from "@/components/Tag.vue";
import Tag from "@/components/TagElement.vue";
import { htmlToText } from "@/utils/html";
import { useI18n } from "vue-i18n";

View File

@@ -8,6 +8,8 @@
@click="clickMap"
@update:zoom="updateZoom"
:options="{ zoomControl: false }"
ref="mapComponent"
@ready="onMapReady"
>
<l-tile-layer :url="tiles?.endpoint" :attribution="attribution">
</l-tile-layer>
@@ -16,28 +18,36 @@
:zoomInTitle="$t('Zoom in')"
:zoomOutTitle="$t('Zoom out')"
></l-control-zoom>
<!-- <v-locatecontrol
v-if="canDoGeoLocation"
:options="{ icon: 'mdi mdi-map-marker' }"
/> -->
<l-marker
:lat-lng="[lat, lon]"
@add="openPopup"
@update:latLng="updateDraggableMarkerPosition"
:draggable="!readOnly"
>
<l-popup v-if="popupMultiLine">
<l-icon>
<MapMarker :size="48" class="text-mbz-purple" />
</l-icon>
<l-popup v-if="popupMultiLine" :options="{ offset: new Point(22, 8) }">
<span v-for="line in popupMultiLine" :key="line"
>{{ line }}<br
/></span>
</l-popup>
</l-marker>
</l-map>
<CrosshairsGps ref="locationIcon" class="hidden" />
</div>
</template>
<script lang="ts" setup>
import { Icon, LatLng, LeafletMouseEvent, LeafletEvent } from "leaflet";
import {
LatLng,
LeafletMouseEvent,
LeafletEvent,
Control,
DomUtil,
Map,
Point,
} from "leaflet";
import "leaflet/dist/leaflet.css";
import {
LMap,
@@ -47,10 +57,12 @@ import {
LIcon,
LControlZoom,
} from "@vue-leaflet/vue-leaflet";
// import Vue2LeafletLocateControl from "@/components/Map/Vue2LeafletLocateControl.vue";
import { computed, nextTick, onMounted, ref } from "vue";
import { useMapTiles } from "@/composition/apollo/config";
import { useI18n } from "vue-i18n";
import Locatecontrol from "leaflet.locatecontrol";
import CrosshairsGps from "vue-material-design-icons/CrosshairsGps.vue";
import MapMarker from "vue-material-design-icons/MapMarker.vue";
const props = withDefaults(
defineProps<{
@@ -77,8 +89,18 @@ const defaultOptions: {
const zoom = ref(defaultOptions.zoom);
onMounted(() => {
const mapComponent = ref();
const mapObject = ref<Map>();
const locateControl = ref<Control.Locate>();
const locationIcon = ref();
const locationIconHTML = computed(() => locationIcon.value?.$el.innerHTML);
onMounted(async () => {
// this part resolve an issue where the markers would not appear
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line no-underscore-dangle
// delete Icon.Default.prototype._getIconUrl;
// Icon.Default.mergeOptions({
// iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
@@ -87,6 +109,50 @@ onMounted(() => {
// });
});
const onMapReady = async () => {
mapObject.value = mapComponent.value.leafletObject;
mountLocateControl();
};
const mountLocateControl = () => {
if (canDoGeoLocation.value && mapObject.value) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
locateControl.value = new Locatecontrol({
strings: { title: t("Show me where I am") as string },
position: "topleft",
drawCircle: false,
drawMarker: false,
createButtonCallback(container: HTMLElement | undefined, options: any) {
const link = DomUtil.create(
"a",
"leaflet-bar-part leaflet-bar-part-single",
container
);
link.title = options.strings.title;
link.href = "#";
link.setAttribute("role", "button");
const icon = DomUtil.create(
"span",
"material-design-icon rss-icon",
link
);
icon.setAttribute("aria-hidden", "true");
icon.setAttribute("role", "img");
icon.insertAdjacentHTML("beforeend", locationIconHTML.value);
console.log("icon for location", {
link,
icon,
});
return { link, icon };
},
...props.options,
}) as Control.Locate;
locateControl.value?.addTo(mapObject.value);
}
};
const openPopup = async (event: LeafletEvent): Promise<void> => {
await nextTick();
event.target.openPopup();
@@ -147,3 +213,6 @@ div.map-container {
}
}
</style>
<style>
@import "leaflet.locatecontrol/dist/L.Control.Locate.css";
</style>

View File

@@ -1,64 +0,0 @@
<template>
<div style="display: none">
<slot v-if="ready"></slot>
</div>
</template>
<script lang="ts">
/**
* Fork of https://github.com/domoritz/leaflet-locatecontrol
* to try to trigger location manually (not done ATM)
*/
import { DomEvent } from "leaflet";
// import { findRealParent, propsBinder } from "vue2-leaflet";
import Locatecontrol from "leaflet.locatecontrol";
import { Component, Prop, Vue } from "vue-property-decorator";
@Component({
beforeDestroy() {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.parentContainer.removeLayer(this);
},
})
export default class Vue2LeafletLocateControl extends Vue {
@Prop({ type: Object, default: () => ({}) }) options!: Record<
string,
unknown
>;
@Prop({ type: Boolean, default: true }) visible!: boolean;
ready = false;
mapObject!: any;
parentContainer: any;
mounted(): void {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.mapObject = new Locatecontrol({
...this.options,
strings: { title: this.$t("Show me where I am") as string },
});
DomEvent.on(this.mapObject, this.$listeners as any);
propsBinder(this, this.mapObject, this.$props);
this.ready = true;
this.parentContainer = findRealParent(this.$parent);
this.mapObject.addTo(this.parentContainer.mapObject, !this.visible);
this.$nextTick(() => {
this.$emit("ready", this.mapObject);
});
}
public locate(): void {
this.mapObject.start();
}
}
</script>
<style>
/* @import "~leaflet.locatecontrol/dist/L.Control.Locate.css"; */
</style>

View File

@@ -86,6 +86,7 @@ import { IMedia } from "@/types/media.model";
import { computed, ref, watch } from "vue";
import { useI18n } from "vue-i18n";
import Upload from "vue-material-design-icons/Upload.vue";
import { formatBytes } from "@/utils/datetime";
const { t } = useI18n({ useScope: "global" });
@@ -140,14 +141,4 @@ watch(imageSrc, () => {
const showImageLoadingError = (): void => {
imagePreviewLoadingError.value = true;
};
// https://gist.github.com/zentala/1e6f72438796d74531803cc3833c039c
const formatBytes = (bytes: number, decimals?: number): string => {
if (bytes == 0) return "0 Bytes";
const k = 1024,
dm = decimals || 2,
sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
};
</script>

View File

@@ -61,7 +61,7 @@ import { formatDateTimeString } from "@/filters/datetime";
import Tag from "vue-material-design-icons/Tag.vue";
import AccountEdit from "vue-material-design-icons/AccountEdit.vue";
import Clock from "vue-material-design-icons/Clock.vue";
import MbzTag from "@/components/Tag.vue";
import MbzTag from "@/components/TagElement.vue";
const props = withDefaults(
defineProps<{

View File

@@ -22,12 +22,17 @@
</div>
<div class="">
<div class="" v-if="comment">
<article class="media">
<div class="media-left">
<figure class="image is-48x48" v-if="comment?.actor?.avatar">
<img :src="comment.actor.avatar.url" alt="" />
<article class="">
<div class="">
<figure class="h-8 w-8" v-if="comment?.actor?.avatar">
<img
:src="comment.actor.avatar.url"
alt=""
width="48"
height="48"
/>
</figure>
<o-icon v-else size="large" icon="account-circle" />
<AccountCircle v-else :size="48" />
</div>
<div class="">
<div class="prose dark:prose-invert">
@@ -65,7 +70,7 @@
</section>
<footer class="flex gap-2 py-3">
<o-button ref="cancelButton" @click="close">
<o-button ref="cancelButton" outlined @click="close">
{{ translatedCancelText }}
</o-button>
<o-button

View File

@@ -75,7 +75,7 @@ import ResourceItem from "@/components/Resource/ResourceItem.vue";
import FolderItem from "@/components/Resource/FolderItem.vue";
import { ref, watch } from "vue";
import { IResource } from "@/types/resource";
import Draggable from "@xiaoshuapp/draggable";
import Draggable from "vuedraggable";
import { IGroup } from "@/types/actor";
const props = withDefaults(
@@ -124,13 +124,13 @@ watch(checkedAll, () => {
});
});
const deleteResource = (resourceID: string) => {
validCheckedResources.value = validCheckedResources.value.filter(
(id) => id !== resourceID
);
delete checkedResources.value[resourceID];
emit("delete", resourceID);
};
// const deleteResource = (resourceID: string) => {
// validCheckedResources.value = validCheckedResources.value.filter(
// (id) => id !== resourceID
// );
// delete checkedResources.value[resourceID];
// emit("delete", resourceID);
// };
</script>
<style lang="scss" scoped>
@use "@/styles/_mixins" as *;

View File

@@ -18,7 +18,7 @@
formatDateTimeString(resource.updatedAt?.toString())
}}</span>
</div>
<!-- <draggable
<draggable
v-if="!inline"
class="dropzone"
v-model="list"
@@ -26,7 +26,7 @@
:sort="false"
:group="groupObject"
@change="onChange"
/> -->
/>
</router-link>
<resource-dropdown
class="actions"
@@ -39,18 +39,18 @@
</template>
<script lang="ts" setup>
import { useRouter } from "vue-router";
// import Draggable, { ChangeEvent } from "@xiaoshuapp/draggable";
// import { SnackbarProgrammatic as Snackbar } from "buefy";
import Draggable, { ChangeEvent } from "vuedraggable";
import { IResource } from "@/types/resource";
import RouteName from "@/router/name";
import { IGroup, usernameWithDomain } from "@/types/actor";
import ResourceDropdown from "./ResourceDropdown.vue";
import { UPDATE_RESOURCE } from "@/graphql/resources";
import { ref } from "vue";
import { inject, ref } from "vue";
import { formatDateTimeString } from "@/filters/datetime";
import { useMutation } from "@vue/apollo-composable";
import { resourcePathArray } from "@/components/Resource/utils";
import Folder from "vue-material-design-icons/Folder.vue";
import { Snackbar } from "@/plugins/snackbar";
const props = withDefaults(
defineProps<{
@@ -77,7 +77,7 @@ const groupObject: Record<string, unknown> = {
const onChange = async (evt: ChangeEvent<IResource>) => {
if (evt.added && evt.added.element) {
const movedResource = evt.added.element as IResource;
// const movedResource = evt.added.element as IResource;
moveResource({
id: props.resource.id,
path: `${props.resource.path}/${props.resource.title}`,
@@ -100,19 +100,20 @@ onMovedResource(({ data }) => {
return router.push({
name: RouteName.RESOURCE_FOLDER,
params: {
path: ResourceMixin.resourcePathArray(props.resource),
path: resourcePathArray(props.resource),
preferredUsername: props.group.preferredUsername,
},
});
}
});
const snackbar = inject<Snackbar>("snackbar");
onMovedResourceError((e) => {
// Snackbar.open({
// message: e.message,
// variant: "danger",
// position: "bottom",
// });
snackbar?.open({
message: e.message,
variant: "danger",
position: "bottom",
});
return undefined;
});
</script>

View File

@@ -60,7 +60,7 @@
<script lang="ts" setup>
import { IResource, mapServiceTypeToIcon } from "@/types/resource";
import ResourceDropdown from "@/components/Resource/ResourceDropdown.vue";
import { ref, computed } from "vue";
import { computed } from "vue";
import { formatDateTimeString } from "@/filters/datetime";
import Link from "vue-material-design-icons/Link.vue";

View File

@@ -2,13 +2,13 @@
<div v-if="loggedUser">
<section>
<div class="setting-title">
<h2>{{ $t("Settings") }}</h2>
<h2>{{ t("Settings") }}</h2>
</div>
<div>
<h3>{{ $t("Language") }}</h3>
<h3>{{ t("Language") }}</h3>
<p>
{{
$t(
t(
"This setting will be used to display the website and send you emails in the correct language."
)
}}
@@ -17,7 +17,7 @@
<o-select
:loading="loading"
v-model="locale"
:placeholder="$t('Select a language')"
:placeholder="t('Select a language')"
>
<option v-for="(language, lang) in langs" :value="lang" :key="lang">
{{ language }}
@@ -27,15 +27,15 @@
</div>
<div>
<h3>{{ $t("Timezone") }}</h3>
<h3>{{ t("Timezone") }}</h3>
<p>
{{
$t(
t(
"We use your timezone to make sure you get notifications for an event at the correct time."
)
}}
{{
$t("Your timezone was detected as {timezone}.", {
t("Your timezone was detected as {timezone}.", {
timezone,
})
}}
@@ -43,7 +43,7 @@
variant="danger"
v-if="!loading && !supportedTimezone"
>
{{ $t("Your timezone {timezone} isn't supported.", { timezone }) }}
{{ t("Your timezone {timezone} isn't supported.", { timezone }) }}
</o-notification>
</p>
</div>
@@ -71,14 +71,14 @@ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const { loggedUser } = useUserSettings();
onMounted(() => {
updateLocale(locale.value);
updateLocale(locale.value as string);
doUpdateSetting({ timezone });
});
watch(locale, () => {
if (locale.value) {
updateLocale(locale.value);
saveLocaleData(locale.value);
updateLocale(locale.value as string);
saveLocaleData(locale.value as string);
}
});

View File

@@ -272,11 +272,11 @@ const isBasicMode = computed((): boolean => {
return props.mode === "basic";
});
const insertMention = (obj: { range: any; attrs: any }) => {
console.debug("initialize Mention");
};
// const insertMention = (obj: { range: any; attrs: any }) => {
// console.debug("initialize Mention");
// };
const observer = ref<MutationObserver | null>(null);
// const observer = ref<MutationObserver | null>(null);
onMounted(() => {
editor.value = new Editor({

View File

@@ -24,14 +24,14 @@
</div>
</template>
<script lang="ts" setup>
// import { SnackbarProgrammatic as Snackbar } from "buefy";
import { ITodo } from "../../types/todos";
import RouteName from "../../router/name";
import { UPDATE_TODO } from "../../graphql/todos";
import { computed, ref } from "vue";
import { computed, inject, ref } from "vue";
import { useMutation } from "@vue/apollo-composable";
import Account from "vue-material-design-icons/Account.vue";
import { formatDateString } from "@/filters/datetime";
import { Snackbar } from "@/plugins/snackbar";
const props = defineProps<{ todo: ITodo }>();
@@ -41,8 +41,8 @@ const status = computed({
get() {
return props.todo.status;
},
set(status: boolean) {
updateTodo({ status, id: props.todo.id });
set(newStatus: boolean) {
updateTodo({ status: newStatus, id: props.todo.id });
},
});
@@ -52,11 +52,13 @@ onDone(() => {
editMode.value = false;
});
const snackbar = inject<Snackbar>("snackbar");
onError((e) => {
// Snackbar.open({
// message: e.message,
// variant: "danger",
// position: "bottom",
// });
snackbar?.open({
message: e.message,
variant: "danger",
position: "bottom",
});
});
</script>

View File

@@ -1,102 +0,0 @@
<template>
<div v-if="attached && closable" class="tags has-addons">
<span class="tag" :class="[variant, size, { rounded }]">
<!-- <o-icon
v-if="icon"
:icon="icon"
:size="size"
:type="iconType"
/> -->
<span :class="{ 'has-ellipsis': ellipsis }" @click="click">
<slot />
</span>
</span>
<a
class="tag"
role="button"
:aria-label="ariaCloseLabel"
:tabindex="tabstop ? 0 : undefined"
:disabled="disabled"
:class="[
size,
closeType,
{ 'is-rounded': rounded },
closeIcon ? 'has-delete-icon' : 'is-delete',
]"
@click="close"
@keyup.delete.prevent="close"
>
<!-- <o-icon
custom-class=""
v-if="closeIcon"
:icon="closeIcon"
:size="size"
:type="closeIconType"
/> -->
</a>
</div>
<span v-else class="tag" :class="[variant, size, { 'is-rounded': rounded }]">
<!-- <o-icon
v-if="icon"
:icon="icon"
:size="size"
:type="iconType"
/> -->
<span :class="{ 'has-ellipsis': ellipsis }" @click="click">
<slot />
</span>
<a
v-if="closable"
role="button"
:aria-label="ariaCloseLabel"
class="delete is-small"
:class="closeType"
:disabled="disabled"
:tabindex="tabstop ? 0 : undefined"
@click="close"
@keyup.delete.prevent="close"
/>
</span>
</template>
<script setup lang="ts">
const props = withDefaults(
defineProps<{
attached?: boolean;
closable?: boolean;
variant?: string;
size?: string;
rounded?: boolean;
disabled?: boolean;
ellipsis?: boolean;
tabstop?: boolean;
ariaCloseLabel?: string;
icon?: string;
iconType?: string;
closeType?: string;
closeIcon?: string;
closeIconType?: string;
}>(),
{
tabstop: true,
}
);
const emit = defineEmits(["close", "click"]);
/**
* Emit close event when delete button is clicked
* or delete key is pressed.
*/
const close = (event: Event) => {
if (props.disabled) return;
emit("close", event);
};
/**
* Emit click event when tag is clicked.
*/
const click = (event: Event) => {
if (props.disabled) return;
emit("click", event);
};
</script>

View File

@@ -26,13 +26,12 @@
<o-field v-if="hasInput">
<o-input
v-model="prompt"
expanded
class="input"
ref="input"
:class="{ 'is-danger': validationMessage }"
v-bind="inputAttrs"
@keydown.enter="confirm"
/>
<p class="help is-danger">{{ validationMessage }}</p>
</o-field>
</div>
</section>
@@ -83,15 +82,14 @@ const emit = defineEmits(["confirm", "cancel", "close"]);
const { t } = useI18n({ useScope: "global" });
const modalOpened = ref(false);
const validationMessage = ref("");
// const modalOpened = ref(false);
const prompt = ref<string>(props.hasInput ? props.inputAttrs?.value ?? "" : "");
const input = ref();
const dialogClass = computed(() => {
return [props.size];
});
// const dialogClass = computed(() => {
// return [props.size];
// });
/**
* Icon name (MDI) based on the type.
*/
@@ -114,10 +112,11 @@ const iconByType = computed(() => {
* Call the onConfirm prop (function) and close the Dialog.
*/
const confirm = () => {
console.log("dialog confirmed", input.value.$el);
if (input.value !== undefined) {
if (!input.value.checkValidity()) {
validationMessage.value = input.value.validationMessage;
nextTick(() => input.value.select());
const inputElement = input.value.$el.querySelector("input");
if (!inputElement.checkValidity()) {
nextTick(() => inputElement.select());
return;
}
}

View File

@@ -54,7 +54,9 @@ const props = withDefaults(
indefinite?: boolean;
}>(),
{
onAction: () => {},
onAction: () => {
// do nothing
},
cancelText: null,
variant: "dark",
position: "bottom-right",