Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2021-11-18 17:50:54 +01:00
parent 32a63a693d
commit dccf397df5
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
217 changed files with 3843 additions and 6061 deletions

View File

@ -15,13 +15,7 @@ config :mobilizon, Mobilizon.Web.Endpoint,
check_origin: false, check_origin: false,
watchers: [ watchers: [
node: [ node: [
"node_modules/webpack/bin/webpack.js", "node_modules/.bin/vite",
"--mode",
"development",
"--watch",
"--watch-options-stdin",
"--config",
"node_modules/@vue/cli-service/webpack.config.js",
cd: Path.expand("../js", __DIR__) cd: Path.expand("../js", __DIR__)
] ]
] ]

View File

@ -3,12 +3,13 @@
"version": "2.0.0-beta.2", "version": "2.0.0-beta.2",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "dev": "tsc --noEmit && vite",
"serve": "vite preview",
"build": "yarn run build:assets && yarn run build:pictures", "build": "yarn run build:assets && yarn run build:pictures",
"test:unit": "LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 TZ=UTC vue-cli-service test:unit", "test:unit": "LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 TZ=UTC vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e", "test:e2e": "vue-cli-service test:e2e",
"lint": "vue-cli-service lint", "lint": "vue-cli-service lint",
"build:assets": "vue-cli-service build", "build:assets": "vite build",
"build:pictures": "bash ./scripts/build/pictures.sh" "build:pictures": "bash ./scripts/build/pictures.sh"
}, },
"dependencies": { "dependencies": {
@ -18,6 +19,7 @@
"@mdi/font": "^6.1.95", "@mdi/font": "^6.1.95",
"@oruga-ui/oruga-next": "^0.4.7", "@oruga-ui/oruga-next": "^0.4.7",
"@oruga-ui/theme-bulma": "^0.1.3", "@oruga-ui/theme-bulma": "^0.1.3",
"@popperjs/core": "^2.10.2",
"@tiptap/core": "^2.0.0-beta.41", "@tiptap/core": "^2.0.0-beta.41",
"@tiptap/extension-blockquote": "^2.0.0-beta.6", "@tiptap/extension-blockquote": "^2.0.0-beta.6",
"@tiptap/extension-bubble-menu": "^2.0.0-beta.9", "@tiptap/extension-bubble-menu": "^2.0.0-beta.9",
@ -31,13 +33,16 @@
"@tiptap/extension-underline": "^2.0.0-beta.7", "@tiptap/extension-underline": "^2.0.0-beta.7",
"@tiptap/starter-kit": "^2.0.0-beta.37", "@tiptap/starter-kit": "^2.0.0-beta.37",
"@tiptap/vue-3": "^2.0.0-beta.81", "@tiptap/vue-3": "^2.0.0-beta.81",
"@variantjs/core": "^0.0.78",
"@variantjs/vue": "^0.0.12",
"@vue-a11y/announcer": "^3.1.5", "@vue-a11y/announcer": "^3.1.5",
"@vue-a11y/skip-to": "^3.0.3", "@vue-a11y/skip-to": "^3.0.3",
"@vue-leaflet/vue-leaflet": "^0.6.1", "@vue-leaflet/vue-leaflet": "^0.6.1",
"@vue/apollo-composable": "^4.0.0-alpha.15", "@vue/apollo-composable": "^4.0.0-alpha.15",
"@vue/apollo-option": "^4.0.0-alpha.15",
"apollo-absinthe-upload-link": "^1.5.0", "apollo-absinthe-upload-link": "^1.5.0",
"blurhash": "^1.1.3", "blurhash": "^1.1.3",
"body-scroll-lock": "^4.0.0-beta.0",
"bulma": "^0.9.3",
"bulma-divider": "^0.2.0", "bulma-divider": "^0.2.0",
"core-js": "^3.6.4", "core-js": "^3.6.4",
"date-fns": "^2.16.0", "date-fns": "^2.16.0",
@ -67,11 +72,14 @@
"vuedraggable": "^2.24.3" "vuedraggable": "^2.24.3"
}, },
"devDependencies": { "devDependencies": {
"@originjs/vite-plugin-commonjs": "^1.0.1",
"@rollup/plugin-dynamic-import-vars": "^1.4.1",
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"@types/leaflet": "^1.5.2", "@types/leaflet": "^1.5.2",
"@types/leaflet.locatecontrol": "^0.60.7", "@types/leaflet.locatecontrol": "^0.60.7",
"@types/lodash": "^4.14.141", "@types/lodash": "^4.14.141",
"@types/ngeohash": "^0.6.2", "@types/ngeohash": "^0.6.2",
"@types/node": "^16.11.7",
"@types/phoenix": "^1.5.2", "@types/phoenix": "^1.5.2",
"@types/prosemirror-inputrules": "^1.0.2", "@types/prosemirror-inputrules": "^1.0.2",
"@types/prosemirror-model": "^1.7.2", "@types/prosemirror-model": "^1.7.2",
@ -80,18 +88,12 @@
"@types/sanitize-html": "^2.5.0", "@types/sanitize-html": "^2.5.0",
"@typescript-eslint/eslint-plugin": "^5.3.0", "@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0", "@typescript-eslint/parser": "^5.3.0",
"@vue/cli-plugin-babel": "~5.0.0-rc.1", "@vitejs/plugin-vue": "^1.9.4",
"@vue/cli-plugin-e2e-cypress": "~5.0.0-rc.1",
"@vue/cli-plugin-eslint": "~5.0.0-rc.1",
"@vue/cli-plugin-pwa": "~5.0.0-rc.1",
"@vue/cli-plugin-router": "~5.0.0-rc.1",
"@vue/cli-plugin-typescript": "~5.0.0-rc.1",
"@vue/cli-plugin-unit-jest": "~5.0.0-rc.1",
"@vue/cli-service": "~5.0.0-rc.1",
"@vue/compiler-sfc": "^3.1.0", "@vue/compiler-sfc": "^3.1.0",
"@vue/eslint-config-typescript": "^9.0.0", "@vue/eslint-config-typescript": "^9.0.0",
"@vue/test-utils": "^2.0.0-rc.16", "@vue/test-utils": "^2.0.0-rc.16",
"@vue/vue3-jest": "^27.0.0-alpha.3", "@vue/vue3-jest": "^27.0.0-alpha.3",
"autoprefixer": "^10.4.0",
"babel-core": "^7.0.0-bridge.0", "babel-core": "^7.0.0-bridge.0",
"cypress": "^8.3.0", "cypress": "^8.3.0",
"eslint": "^8.2.0", "eslint": "^8.2.0",
@ -104,12 +106,17 @@
"jest": "^27.1.0", "jest": "^27.1.0",
"jest-junit": "^13.0.0", "jest-junit": "^13.0.0",
"mock-apollo-client": "^1.1.0", "mock-apollo-client": "^1.1.0",
"postcss": "^8.3.11",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"prettier-eslint": "^13.0.0", "prettier-eslint": "^13.0.0",
"sass": "^1.34.1", "sass": "^1.43.4",
"sass-loader": "^12.0.0", "sass-loader": "^12.0.0",
"tailwindcss": "^2.2.19",
"ts-jest": "27", "ts-jest": "27",
"typescript": "~4.4.3", "typescript": "^4.5.2",
"vite": "^2.6.14",
"vite-plugin-html": "^2.1.1",
"vite-plugin-pwa": "^0.11.5",
"vue-i18n-extract": "^2.0.4", "vue-i18n-extract": "^2.0.4",
"webpack-cli": "^4.7.0" "webpack-cli": "^4.7.0"
} }

6
js/postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,22 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" dir="auto"> <html lang="en" dir="auto">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<meta name="server-injected-data" />
</head>
<body> <head>
<noscript> <meta charset="utf-8" />
<strong <meta http-equiv="X-UA-Compatible" content="IE=edge" />
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work <meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<meta name="server-injected-data" />
<script type="module" src="http://localhost:3000/@vite/client"></script>
<script type="module" src="http://localhost:3000/src/main.ts"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to properly without JavaScript enabled. Please enable it to
continue.</strong continue.</strong>
> </noscript>
</noscript> <div id="app"></div>
<div id="app"></div> <!-- built files will be auto injected -->
<!-- built files will be auto injected --> </body>
</body>
</html> </html>

View File

@ -26,7 +26,7 @@
<main id="main" v-else> <main id="main" v-else>
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<!-- <router-view ref="routerView" /> --> <router-view ref="routerView" />
</transition> </transition>
</main> </main>
<mobilizon-footer /> <mobilizon-footer />
@ -53,7 +53,12 @@ import { ICurrentUser } from "./types/current-user.model";
import jwt_decode, { JwtPayload } from "jwt-decode"; import jwt_decode, { JwtPayload } from "jwt-decode";
import { refreshAccessToken } from "./apollo/utils"; import { refreshAccessToken } from "./apollo/utils";
import { defineComponent, ref } from "vue"; import { defineComponent, ref } from "vue";
import { useMutation, useQuery, useResult } from "@vue/apollo-composable"; import {
useApolloClient,
useMutation,
useQuery,
useResult,
} from "@vue/apollo-composable";
import { RouterView } from "vue-router"; import { RouterView } from "vue-router";
import { useAnnouncer } from "@vue-a11y/announcer"; import { useAnnouncer } from "@vue-a11y/announcer";
import { useMeta } from "vue-meta"; import { useMeta } from "vue-meta";
@ -76,6 +81,8 @@ export default defineComponent({
useMeta({ titleTemplate: "%s | Mobilizon" }); useMeta({ titleTemplate: "%s | Mobilizon" });
const { resolveClient } = useApolloClient();
return { return {
config, config,
currentUser, currentUser,
@ -83,6 +90,7 @@ export default defineComponent({
online: false, online: false,
interval, interval,
routerView, routerView,
resolveClient,
}; };
}, },
components: { components: {
@ -91,11 +99,6 @@ export default defineComponent({
import(/* webpackChunkName: "editor" */ "./components/Error.vue"), import(/* webpackChunkName: "editor" */ "./components/Error.vue"),
"mobilizon-footer": Footer, "mobilizon-footer": Footer,
}, },
async created(): Promise<void> {
if (await this.initializeCurrentUser()) {
await initializeCurrentActor(this.$apollo.provider.defaultClient);
}
},
methods: { methods: {
async initializeCurrentUser(): Promise<boolean> { async initializeCurrentUser(): Promise<boolean> {
const userId = localStorage.getItem(AUTH_USER_ID); const userId = localStorage.getItem(AUTH_USER_ID);
@ -145,7 +148,10 @@ export default defineComponent({
return document.title; return document.title;
}, },
}, },
mounted(): void { async mounted(): Promise<void> {
if (await this.initializeCurrentUser()) {
await initializeCurrentActor(this.resolveClient());
}
this.online = window.navigator.onLine; this.online = window.navigator.onLine;
window.addEventListener("offline", () => { window.addEventListener("offline", () => {
this.online = false; this.online = false;
@ -192,7 +198,7 @@ export default defineComponent({
token?.exp !== undefined && token?.exp !== undefined &&
new Date(token.exp * 1000 - 60000) < new Date() new Date(token.exp * 1000 - 60000) < new Date()
) { ) {
refreshAccessToken(this.$apollo.getClient()); refreshAccessToken(this.resolveClient());
} }
} }
}, 60000); }, 60000);
@ -237,7 +243,7 @@ export default defineComponent({
/* Icons */ /* Icons */
$mdi-font-path: "~@mdi/font/fonts"; $mdi-font-path: "~@mdi/font/fonts";
@import "~@mdi/font/scss/materialdesignicons"; @import "../node_modules/@mdi/font/scss/materialdesignicons";
@import "common"; @import "common";
#mobilizon { #mobilizon {

View File

@ -1,9 +1,9 @@
@use "@/styles/_mixins" as *; @use "@/styles/_mixins" as *;
@import "variables.scss"; @import "variables.scss";
@import "~bulma"; // @import "../node_modules/bulma/bulma.sass";
@import "~bulma-divider"; // @import "../node_modules/bulma-divider/dist/css/bulma-divider.sass";
@import "~buefy/src/scss/buefy"; // @import "~buefy/src/scss/buefy";
@import "styles/vue-announcer.scss"; @import "styles/vue-announcer.scss";
@import "styles/vue-skip-to.scss"; @import "styles/vue-skip-to.scss";

View File

@ -8,9 +8,8 @@
</p> </p>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class InstanceContactLink extends Vue { export default class InstanceContactLink extends Vue {
@Prop({ required: true, type: String }) contact!: string; @Prop({ required: true, type: String }) contact!: string;

View File

@ -36,15 +36,10 @@
</div> </div>
</div> </div>
</template> </template>
<template slot="footer">
<span class="has-text-grey" v-show="page > totalPages">
Thats it! No more movies found.
</span>
</template>
</o-autocomplete> </o-autocomplete>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Model, Vue, Watch } from "vue-property-decorator"; import { Model, Vue, Watch } from "vue-property-decorator";
import debounce from "lodash/debounce"; import debounce from "lodash/debounce";
import { IPerson } from "@/types/actor"; import { IPerson } from "@/types/actor";
import { SEARCH_PERSONS } from "@/graphql/search"; import { SEARCH_PERSONS } from "@/graphql/search";
@ -52,7 +47,6 @@ import { Paginate } from "@/types/paginate";
const SEARCH_PERSON_LIMIT = 10; const SEARCH_PERSON_LIMIT = 10;
@Component
export default class ActorAutoComplete extends Vue { export default class ActorAutoComplete extends Vue {
@Model("change", { type: Object }) readonly defaultSelected!: IPerson | null; @Model("change", { type: Object }) readonly defaultSelected!: IPerson | null;

View File

@ -24,10 +24,9 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Vue, Prop } from "vue-property-decorator";
import { IActor, usernameWithDomain } from "../../types/actor"; import { IActor, usernameWithDomain } from "../../types/actor";
@Component
export default class ActorCard extends Vue { export default class ActorCard extends Vue {
@Prop({ required: true, type: Object }) actor!: IActor; @Prop({ required: true, type: Object }) actor!: IActor;

View File

@ -15,10 +15,9 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Vue, Prop } from "vue-property-decorator";
import { IActor, usernameWithDomain } from "../../types/actor"; import { IActor, usernameWithDomain } from "../../types/actor";
@Component
export default class ActorInline extends Vue { export default class ActorInline extends Vue {
@Prop({ required: true, type: Object }) actor!: IActor; @Prop({ required: true, type: Object }) actor!: IActor;

View File

@ -37,11 +37,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { IDENTITIES } from "../../graphql/actor"; import { IDENTITIES } from "../../graphql/actor";
import { IPerson, Person } from "../../types/actor"; import { IPerson, Person } from "../../types/actor";
@Component({ @Options({
apollo: { apollo: {
identities: { identities: {
query: IDENTITIES, query: IDENTITIES,

View File

@ -13,11 +13,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ActorType } from "@/types/enums"; import { ActorType } from "@/types/enums";
import { Component, Vue, Prop } from "vue-property-decorator"; import { Options, Vue, Prop } from "vue-property-decorator";
import { IActor } from "../../types/actor"; import { IActor } from "../../types/actor";
import ActorCard from "./ActorCard.vue"; import ActorCard from "./ActorCard.vue";
@Component({ @Options({
components: { components: {
ActorCard, ActorCard,
}, },

View File

@ -53,9 +53,9 @@ import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import { CONFIG } from "@/graphql/config"; import { CONFIG } from "@/graphql/config";
import { IPerson } from "@/types/actor"; import { IPerson } from "@/types/actor";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
import { Component, Vue } from "vue-property-decorator"; import { Options, Vue } from "vue-property-decorator";
@Component({ @Options({
apollo: { apollo: {
config: CONFIG, config: CONFIG,
currentActor: CURRENT_ACTOR_CLIENT, currentActor: CURRENT_ACTOR_CLIENT,

View File

@ -54,13 +54,13 @@
<script lang="ts"> <script lang="ts">
import { usernameWithDomain } from "@/types/actor"; import { usernameWithDomain } from "@/types/actor";
import { ActivityDiscussionSubject } from "@/types/enums"; import { ActivityDiscussionSubject } from "@/types/enums";
import { Component } from "vue-property-decorator"; import { Options } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
import ActivityMixin from "../../mixins/activity"; import ActivityMixin from "../../mixins/activity";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
@Component({ @Options({
components: { components: {
PopoverActorCard, PopoverActorCard,
}, },

View File

@ -40,12 +40,12 @@ import {
ActivityEventSubject, ActivityEventSubject,
} from "@/types/enums"; } from "@/types/enums";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
import { Component } from "vue-property-decorator"; import { Options } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
import ActivityMixin from "../../mixins/activity"; import ActivityMixin from "../../mixins/activity";
@Component({ @Options({
components: { components: {
PopoverActorCard, PopoverActorCard,
}, },

View File

@ -72,13 +72,13 @@
<script lang="ts"> <script lang="ts">
import { usernameWithDomain } from "@/types/actor"; import { usernameWithDomain } from "@/types/actor";
import { ActivityGroupSubject, GroupVisibility, Openness } from "@/types/enums"; import { ActivityGroupSubject, GroupVisibility, Openness } from "@/types/enums";
import { Component } from "vue-property-decorator"; import { Options } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
import ActivityMixin from "../../mixins/activity"; import ActivityMixin from "../../mixins/activity";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
@Component({ @Options({
components: { components: {
PopoverActorCard, PopoverActorCard,
}, },

View File

@ -31,7 +31,7 @@
<script lang="ts"> <script lang="ts">
import { displayName } from "@/types/actor"; import { displayName } from "@/types/actor";
import { ActivityMemberSubject, MemberRole } from "@/types/enums"; import { ActivityMemberSubject, MemberRole } from "@/types/enums";
import { Component } from "vue-property-decorator"; import { Options } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
import ActivityMixin from "../../mixins/activity"; import ActivityMixin from "../../mixins/activity";
@ -44,7 +44,7 @@ export const MEMBER_ROLE_VALUE: Record<string, number> = {
[MemberRole.CREATOR]: 100, [MemberRole.CREATOR]: 100,
}; };
@Component({ @Options({
components: { components: {
PopoverActorCard, PopoverActorCard,
}, },

View File

@ -36,13 +36,13 @@
<script lang="ts"> <script lang="ts">
import { usernameWithDomain } from "@/types/actor"; import { usernameWithDomain } from "@/types/actor";
import { ActivityPostSubject } from "@/types/enums"; import { ActivityPostSubject } from "@/types/enums";
import { Component } from "vue-property-decorator"; import { Options } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
import ActivityMixin from "../../mixins/activity"; import ActivityMixin from "../../mixins/activity";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
@Component({ @Options({
components: { components: {
PopoverActorCard, PopoverActorCard,
}, },

View File

@ -46,14 +46,14 @@
<script lang="ts"> <script lang="ts">
import { usernameWithDomain } from "@/types/actor"; import { usernameWithDomain } from "@/types/actor";
import { ActivityResourceSubject } from "@/types/enums"; import { ActivityResourceSubject } from "@/types/enums";
import { Component } from "vue-property-decorator"; import { Options } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
import ActivityMixin from "../../mixins/activity"; import ActivityMixin from "../../mixins/activity";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
import { Location } from "vue-router"; import { Location } from "vue-router";
@Component({ @Options({
components: { components: {
PopoverActorCard, PopoverActorCard,
}, },

View File

@ -44,9 +44,8 @@
<script lang="ts"> <script lang="ts">
import { IAddress } from "@/types/address.model"; import { IAddress } from "@/types/address.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class AddressInfo extends Vue { export default class AddressInfo extends Vue {
@Prop({ required: true, type: Object as PropType<IAddress> }) @Prop({ required: true, type: Object as PropType<IAddress> })
address!: IAddress; address!: IAddress;

View File

@ -20,9 +20,8 @@
<script lang="ts"> <script lang="ts">
import { IAddress } from "@/types/address.model"; import { IAddress } from "@/types/address.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Prop, Vue, Component } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class InlineAddress extends Vue { export default class InlineAddress extends Vue {
@Prop({ required: true, type: Object as PropType<IAddress> }) @Prop({ required: true, type: Object as PropType<IAddress> })
physicalAddress!: IAddress; physicalAddress!: IAddress;

View File

@ -128,8 +128,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Mixins } from "vue-property-decorator"; import { Options, mixins } from "vue-property-decorator";
import { SnackbarProgrammatic as Snackbar } from "buefy"; // import { SnackbarProgrammatic as Snackbar } from "buefy";
import { formatDistanceToNow } from "date-fns"; import { formatDistanceToNow } from "date-fns";
import { import {
ACCEPT_RELAY, ACCEPT_RELAY,
@ -143,7 +143,7 @@ import { Paginate } from "@/types/paginate";
const FOLLOWERS_PER_PAGE = 10; const FOLLOWERS_PER_PAGE = 10;
@Component({ @Options({
apollo: { apollo: {
relayFollowers: { relayFollowers: {
query: RELAY_FOLLOWERS, query: RELAY_FOLLOWERS,
@ -162,7 +162,7 @@ const FOLLOWERS_PER_PAGE = 10;
}; };
}, },
}) })
export default class Followers extends Mixins(RelayMixin) { export default class Followers extends mixins(RelayMixin) {
RelayMixin = RelayMixin; RelayMixin = RelayMixin;
formatDistanceToNow = formatDistanceToNow; formatDistanceToNow = formatDistanceToNow;
@ -211,11 +211,11 @@ export default class Followers extends Mixins(RelayMixin) {
this.checkedRows = []; this.checkedRows = [];
} catch (e: any) { } catch (e: any) {
if (e.message) { if (e.message) {
Snackbar.open({ // Snackbar.open({
message: e.message, // message: e.message,
type: "is-danger", // type: "is-danger",
position: "is-bottom", // position: "is-bottom",
}); // });
} }
} }
} }
@ -232,11 +232,11 @@ export default class Followers extends Mixins(RelayMixin) {
this.checkedRows = []; this.checkedRows = [];
} catch (e: any) { } catch (e: any) {
if (e.message) { if (e.message) {
Snackbar.open({ // Snackbar.open({
message: e.message, // message: e.message,
type: "is-danger", // type: "is-danger",
position: "is-bottom", // position: "is-bottom",
}); // });
} }
} }
} }

View File

@ -138,8 +138,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Mixins } from "vue-property-decorator"; import { Options, mixins } from "vue-property-decorator";
import { SnackbarProgrammatic as Snackbar } from "buefy"; // import { SnackbarProgrammatic as Snackbar } from "buefy";
import { formatDistanceToNow } from "date-fns"; import { formatDistanceToNow } from "date-fns";
import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin"; import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin";
import { IFollower } from "../../types/actor/follower.model"; import { IFollower } from "../../types/actor/follower.model";
@ -152,7 +152,7 @@ import gql from "graphql-tag";
const FOLLOWINGS_PER_PAGE = 10; const FOLLOWINGS_PER_PAGE = 10;
@Component({ @Options({
apollo: { apollo: {
relayFollowings: { relayFollowings: {
query: RELAY_FOLLOWINGS, query: RELAY_FOLLOWINGS,
@ -171,7 +171,7 @@ const FOLLOWINGS_PER_PAGE = 10;
}; };
}, },
}) })
export default class Followings extends Mixins(RelayMixin) { export default class Followings extends mixins(RelayMixin) {
newRelayAddress = ""; newRelayAddress = "";
RelayMixin = RelayMixin; RelayMixin = RelayMixin;
@ -256,11 +256,11 @@ export default class Followings extends Mixins(RelayMixin) {
this.newRelayAddress = ""; this.newRelayAddress = "";
} catch (err: any) { } catch (err: any) {
if (err.message) { if (err.message) {
Snackbar.open({ // Snackbar.open({
message: err.message, // message: err.message,
type: "is-danger", // type: "is-danger",
position: "is-bottom", // position: "is-bottom",
}); // });
} }
} }
} }

View File

@ -179,9 +179,9 @@
</li> </li>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Ref } from "vue-property-decorator"; import { Options, Prop, Vue, Ref } from "vue-property-decorator";
import EditorComponent from "@/components/Editor.vue"; import EditorComponent from "@/components/Editor.vue";
import { SnackbarProgrammatic as Snackbar } from "buefy"; // import { SnackbarProgrammatic as Snackbar } from "buefy";
import { formatDistanceToNow } from "date-fns"; import { formatDistanceToNow } from "date-fns";
import { CommentModeration } from "@/types/enums"; import { CommentModeration } from "@/types/enums";
import { CommentModel, IComment } from "../../types/comment.model"; import { CommentModel, IComment } from "../../types/comment.model";
@ -193,7 +193,7 @@ import { IReport } from "../../types/report.model";
import { CREATE_REPORT } from "../../graphql/report"; import { CREATE_REPORT } from "../../graphql/report";
import PopoverActorCard from "../Account/PopoverActorCard.vue"; import PopoverActorCard from "../Account/PopoverActorCard.vue";
@Component({ @Options({
apollo: { apollo: {
currentActor: { currentActor: {
query: CURRENT_ACTOR_CLIENT, query: CURRENT_ACTOR_CLIENT,
@ -295,7 +295,7 @@ export default class Comment extends Vue {
reportModal(): void { reportModal(): void {
if (!this.comment.actor) return; if (!this.comment.actor) return;
this.$buefy.modal.open({ this.$oruga.modal.open({
parent: this, parent: this,
component: ReportModal, component: ReportModal,
props: { props: {
@ -324,7 +324,7 @@ export default class Comment extends Vue {
forward, forward,
}, },
}); });
this.$buefy.notification.open({ this.$oruga.notification.open({
message: this.$t("Comment from @{username} reported", { message: this.$t("Comment from @{username} reported", {
username: this.comment.actor.preferredUsername, username: this.comment.actor.preferredUsername,
}) as string, }) as string,
@ -334,11 +334,11 @@ export default class Comment extends Vue {
}); });
} catch (e: any) { } catch (e: any) {
if (e.message) { if (e.message) {
Snackbar.open({ // Snackbar.open({
message: e.message, // message: e.message,
type: "is-danger", // type: "is-danger",
position: "is-bottom", // position: "is-bottom",
}); // });
} }
} }
} }

View File

@ -85,7 +85,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Prop, Vue, Component, Watch } from "vue-property-decorator"; import { Prop, Vue, Options, Watch } from "vue-property-decorator";
import Comment from "@/components/Comment/Comment.vue"; import Comment from "@/components/Comment/Comment.vue";
import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue"; import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
import { CommentModeration } from "@/types/enums"; import { CommentModeration } from "@/types/enums";
@ -101,7 +101,7 @@ import { IEvent } from "../../types/event.model";
import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core";
import EmptyContent from "@/components/Utils/EmptyContent.vue"; import EmptyContent from "@/components/Utils/EmptyContent.vue";
@Component({ @Options({
apollo: { apollo: {
currentActor: CURRENT_ACTOR_CLIENT, currentActor: CURRENT_ACTOR_CLIENT,
comments: { comments: {
@ -366,7 +366,7 @@ export default class CommentTree extends Vue {
<style lang="scss" scoped> <style lang="scss" scoped>
@use "@/styles/_mixins" as *; @use "@/styles/_mixins" as *;
@import "~bulma/sass/utilities/mixins.sass"; @import "../node_modules/bulma/sass/utilities/mixins.sass";
form.new-comment { form.new-comment {
padding-bottom: 1rem; padding-bottom: 1rem;

View File

@ -109,13 +109,13 @@
</article> </article>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { formatDistanceToNow } from "date-fns"; import { formatDistanceToNow } from "date-fns";
import { IComment } from "../../types/comment.model"; import { IComment } from "../../types/comment.model";
import { usernameWithDomain, IPerson } from "../../types/actor"; import { usernameWithDomain, IPerson } from "../../types/actor";
import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
@Component({ @Options({
apollo: { apollo: {
currentActor: CURRENT_ACTOR_CLIENT, currentActor: CURRENT_ACTOR_CLIENT,
}, },

View File

@ -50,12 +50,11 @@
</router-link> </router-link>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
import { formatDistanceToNowStrict } from "date-fns"; import { formatDistanceToNowStrict } from "date-fns";
import { IDiscussion } from "../../types/discussions"; import { IDiscussion } from "../../types/discussions";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component
export default class DiscussionListItem extends Vue { export default class DiscussionListItem extends Vue {
@Prop({ required: true, type: Object }) discussion!: IDiscussion; @Prop({ required: true, type: Object }) discussion!: IDiscussion;

View File

@ -193,8 +193,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import { Options, Prop, Vue, Watch } from "vue-property-decorator";
import { Editor, EditorContent, BubbleMenu } from "@tiptap/vue-2"; import { Editor, EditorContent, BubbleMenu } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit"; import StarterKit from "@tiptap/starter-kit";
import Document from "@tiptap/extension-document"; import Document from "@tiptap/extension-document";
import Paragraph from "@tiptap/extension-paragraph"; import Paragraph from "@tiptap/extension-paragraph";
@ -214,7 +214,7 @@ import CharacterCount from "@tiptap/extension-character-count";
import { AutoDir } from "./Editor/Autodir"; import { AutoDir } from "./Editor/Autodir";
import sanitizeHtml from "sanitize-html"; import sanitizeHtml from "sanitize-html";
@Component({ @Options({
components: { EditorContent, BubbleMenu }, components: { EditorContent, BubbleMenu },
apollo: { apollo: {
currentActor: { currentActor: {
@ -319,17 +319,17 @@ export default class EditorComponent extends Vue {
* Show a popup to get the link from the URL * Show a popup to get the link from the URL
*/ */
showLinkMenu(): void { showLinkMenu(): void {
this.$buefy.dialog.prompt({ // this.$buefy.dialog.prompt({
message: this.$t("Enter the link URL") as string, // message: this.$t("Enter the link URL") as string,
inputAttrs: { // inputAttrs: {
type: "url", // type: "url",
}, // },
trapFocus: true, // trapFocus: true,
onConfirm: (value) => { // onConfirm: (value) => {
if (!this.editor) return undefined; // if (!this.editor) return undefined;
this.editor.chain().focus().setLink({ href: value }).run(); // this.editor.chain().focus().setLink({ href: value }).run();
}, // },
}); // });
} }
/** /**

View File

@ -1,5 +1,5 @@
import { UPLOAD_MEDIA } from "@/graphql/upload"; import { UPLOAD_MEDIA } from "@/graphql/upload";
import apolloProvider from "@/vue-apollo"; import { apolloClient } from "@/vue-apollo";
import { ApolloClient } from "@apollo/client/core/ApolloClient"; import { ApolloClient } from "@apollo/client/core/ApolloClient";
import { Plugin } from "prosemirror-state"; import { Plugin } from "prosemirror-state";
import { EditorView } from "prosemirror-view"; import { EditorView } from "prosemirror-view";
@ -61,7 +61,7 @@ const CustomImage = Image.extend({
}); });
if (!coordinates) return false; if (!coordinates) return false;
const client = const client =
apolloProvider.defaultClient as ApolloClient<NormalizedCacheObject>; apolloClient as ApolloClient<NormalizedCacheObject>;
try { try {
images.forEach(async (image) => { images.forEach(async (image) => {

View File

@ -1,15 +1,14 @@
import { SEARCH_PERSONS } from "@/graphql/search"; import { SEARCH_PERSONS } from "@/graphql/search";
import { VueRenderer } from "@tiptap/vue-2"; import { VueRenderer } from "@tiptap/vue-3";
import tippy from "tippy.js"; import tippy from "tippy.js";
import MentionList from "./MentionList.vue"; import MentionList from "./MentionList.vue";
import { ApolloClient } from "@apollo/client/core/ApolloClient"; import { ApolloClient } from "@apollo/client/core/ApolloClient";
import apolloProvider from "@/vue-apollo"; import { apolloClient } from "@/vue-apollo";
import { IPerson } from "@/types/actor"; import { IPerson } from "@/types/actor";
import pDebounce from "p-debounce"; import pDebounce from "p-debounce";
import { NormalizedCacheObject } from "@apollo/client/cache/inmemory/types"; import { NormalizedCacheObject } from "@apollo/client/cache/inmemory/types";
const client = const client = apolloClient as ApolloClient<NormalizedCacheObject>;
apolloProvider.defaultClient as ApolloClient<NormalizedCacheObject>;
const fetchItems = async (query: string): Promise<IPerson[]> => { const fetchItems = async (query: string): Promise<IPerson[]> => {
const result = await client.query({ const result = await client.query({
@ -43,6 +42,8 @@ const mentionOptions: Partial<any> = {
return { return {
onStart: (props: any) => { onStart: (props: any) => {
component = new VueRenderer(MentionList, { component = new VueRenderer(MentionList, {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
parent: this, parent: this,
propsData: props, propsData: props,
}); });

View File

@ -13,12 +13,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Vue, Component, Prop, Watch } from "vue-property-decorator"; import { Vue, Options, Prop, Watch } from "vue-property-decorator";
import { displayName, usernameWithDomain } from "@/types/actor/actor.model"; import { displayName, usernameWithDomain } from "@/types/actor/actor.model";
import { IPerson } from "@/types/actor"; import { IPerson } from "@/types/actor";
import ActorCard from "../../components/Account/ActorCard.vue"; import ActorCard from "../../components/Account/ActorCard.vue";
@Component({ @Options({
components: { components: {
ActorCard, ActorCard,
}, },

View File

@ -118,9 +118,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { CONTACT } from "@/graphql/config"; import { CONTACT } from "@/graphql/config";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
@Component({ @Options({
apollo: { apollo: {
config: { config: {
query: CONTACT, query: CONTACT,

View File

@ -59,14 +59,14 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Mixins, Prop, Watch } from "vue-property-decorator"; import { Options, mixins, Prop, Watch } from "vue-property-decorator";
import { Address, IAddress } from "../../types/address.model"; import { Address, IAddress } from "../../types/address.model";
import AddressAutoCompleteMixin from "@/mixins/AddressAutoCompleteMixin"; import AddressAutoCompleteMixin from "@/mixins/AddressAutoCompleteMixin";
@Component({ @Options({
inheritAttrs: false, inheritAttrs: false,
}) })
export default class AddressAutoComplete extends Mixins( export default class AddressAutoComplete extends mixins(
AddressAutoCompleteMixin AddressAutoCompleteMixin
) { ) {
@Prop({ required: false, default: false }) type!: string | false; @Prop({ required: false, default: false }) type!: string | false;

View File

@ -1,16 +1,3 @@
<docs>
### Example
```vue
<DateCalendarIcon date="2019-10-05T18:41:11.720Z" />
```
```vue
<DateCalendarIcon
:date="new Date()"
/>
```
</docs>
<template> <template>
<div <div
class="datetime-container" class="datetime-container"
@ -25,9 +12,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class DateCalendarIcon extends Vue { export default class DateCalendarIcon extends Vue {
/** /**
* `date` can be a string or an actual date object. * `date` can be a string or an actual date object.
@ -36,7 +22,7 @@ export default class DateCalendarIcon extends Vue {
@Prop({ required: false, default: false }) small!: boolean; @Prop({ required: false, default: false }) small!: boolean;
get dateObj(): Date { get dateObj(): Date {
return new Date(this.$props.date); return new Date(this.date);
} }
get month(): string { get month(): string {

View File

@ -6,10 +6,10 @@
<script lang="ts"> <script lang="ts">
import { IMedia } from "@/types/media.model"; import { IMedia } from "@/types/media.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import LazyImageWrapper from "../Image/LazyImageWrapper.vue"; import LazyImageWrapper from "../Image/LazyImageWrapper.vue";
@Component({ @Options({
components: { components: {
LazyImageWrapper, LazyImageWrapper,
}, },

View File

@ -92,7 +92,7 @@ import {
organizerDisplayName, organizerDisplayName,
organizer, organizer,
} from "@/types/event.model"; } from "@/types/event.model";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue"; import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
import { Actor, Person } from "@/types/actor"; import { Actor, Person } from "@/types/actor";
@ -100,7 +100,7 @@ import { EventStatus, ParticipantRole } from "@/types/enums";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import InlineAddress from "@/components/Address/InlineAddress.vue"; import InlineAddress from "@/components/Address/InlineAddress.vue";
@Component({ @Options({
components: { components: {
DateCalendarIcon, DateCalendarIcon,
LazyImageWrapper, LazyImageWrapper,

View File

@ -1,22 +1,3 @@
<docs>
#### Give a translated and localized text that give the starting and ending datetime for an event.
##### Start date with no ending
```vue
<EventFullDate beginsOn="2015-10-06T18:41:11.720Z" />
```
##### Start date with an ending the same day
```vue
<EventFullDate beginsOn="2015-10-06T18:41:11.720Z" endsOn="2015-10-06T20:41:11.720Z" />
```
##### Start date with an ending on a different day
```vue
<EventFullDate beginsOn="2015-10-06T18:41:11.720Z" endsOn="2032-10-06T18:41:11.720Z" />
```
</docs>
<template> <template>
<p v-if="!endsOn"> <p v-if="!endsOn">
<span>{{ <span>{{
@ -112,9 +93,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { getTimezoneOffset } from "date-fns-tz"; import { getTimezoneOffset } from "date-fns-tz";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class EventFullDate extends Vue { export default class EventFullDate extends Vue {
@Prop({ required: true }) beginsOn!: string; @Prop({ required: true }) beginsOn!: string;

View File

@ -75,7 +75,7 @@
<script lang="ts"> <script lang="ts">
import { IEventCardOptions, IEvent } from "@/types/event.model"; import { IEventCardOptions, IEvent } from "@/types/event.model";
import { Component, Prop } from "vue-property-decorator"; import { Options, Prop } from "vue-property-decorator";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { IPerson, usernameWithDomain } from "@/types/actor"; import { IPerson, usernameWithDomain } from "@/types/actor";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
@ -93,7 +93,7 @@ const defaultOptions: IEventCardOptions = {
memberofGroup: false, memberofGroup: false,
}; };
@Component({ @Options({
components: { components: {
DateCalendarIcon, DateCalendarIcon,
}, },

View File

@ -70,7 +70,7 @@
import { Address, IAddress } from "@/types/address.model"; import { Address, IAddress } from "@/types/address.model";
import { RoutingTransportationType, RoutingType } from "@/types/enums"; import { RoutingTransportationType, RoutingType } from "@/types/enums";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Vue, Prop } from "vue-property-decorator"; import { Options, Vue, Prop } from "vue-property-decorator";
const RoutingParamType = { const RoutingParamType = {
[RoutingType.OPENSTREETMAP]: { [RoutingType.OPENSTREETMAP]: {
@ -87,7 +87,7 @@ const RoutingParamType = {
}, },
}; };
@Component({ @Options({
components: { components: {
"map-leaflet": () => "map-leaflet": () =>
import(/* webpackChunkName: "map" */ "../../components/Map.vue"), import(/* webpackChunkName: "map" */ "../../components/Map.vue"),

View File

@ -21,9 +21,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class EventMetadataBlock extends Vue { export default class EventMetadataBlock extends Vue {
@Prop({ required: false, type: String }) icon!: string; @Prop({ required: false, type: String }) icon!: string;

View File

@ -83,9 +83,8 @@
import { EventMetadataKeyType, EventMetadataType } from "@/types/enums"; import { EventMetadataKeyType, EventMetadataType } from "@/types/enums";
import { IEventMetadataDescription } from "@/types/event-metadata"; import { IEventMetadataDescription } from "@/types/event-metadata";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Ref, Vue } from "vue-property-decorator"; import { Prop, Ref, Vue } from "vue-property-decorator";
@Component
export default class EventMetadataItem extends Vue { export default class EventMetadataItem extends Vue {
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true }) @Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
value!: IEventMetadataDescription; value!: IEventMetadataDescription;

View File

@ -99,7 +99,7 @@ import {
} from "@/types/event-metadata"; } from "@/types/event-metadata";
import cloneDeep from "lodash/cloneDeep"; import cloneDeep from "lodash/cloneDeep";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import EventMetadataItem from "./EventMetadataItem.vue"; import EventMetadataItem from "./EventMetadataItem.vue";
import { eventMetaDataList } from "../../services/EventMetadata"; import { eventMetaDataList } from "../../services/EventMetadata";
import { EventMetadataCategories, EventMetadataType } from "@/types/enums"; import { EventMetadataCategories, EventMetadataType } from "@/types/enums";
@ -109,7 +109,7 @@ type GroupedIEventMetadata = Array<{
items: IEventMetadata[]; items: IEventMetadata[];
}>; }>;
@Component({ @Options({
components: { components: {
EventMetadataItem, EventMetadataItem,
}, },

View File

@ -141,7 +141,7 @@ import { IConfig } from "@/types/config.model";
import { EventMetadataKeyType, EventMetadataType } from "@/types/enums"; import { EventMetadataKeyType, EventMetadataType } from "@/types/enums";
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import { usernameWithDomain } from "../../types/actor"; import { usernameWithDomain } from "../../types/actor";
import EventMetadataBlock from "./EventMetadataBlock.vue"; import EventMetadataBlock from "./EventMetadataBlock.vue";
@ -156,7 +156,7 @@ import {
import { eventMetaDataList } from "../../services/EventMetadata"; import { eventMetaDataList } from "../../services/EventMetadata";
import { IUser } from "@/types/current-user.model"; import { IUser } from "@/types/current-user.model";
@Component({ @Options({
components: { components: {
EventMetadataBlock, EventMetadataBlock,
EventFullDate, EventFullDate,

View File

@ -102,7 +102,7 @@
</router-link> </router-link>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { IEvent, organizer, organizerDisplayName } from "@/types/event.model"; import { IEvent, organizer, organizerDisplayName } from "@/types/event.model";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { ParticipantRole } from "@/types/enums"; import { ParticipantRole } from "@/types/enums";
@ -110,7 +110,7 @@ import RouteName from "../../router/name";
import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue"; import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
import InlineAddress from "@/components/Address/InlineAddress.vue"; import InlineAddress from "@/components/Address/InlineAddress.vue";
@Component({ @Options({
components: { components: {
DateCalendarIcon, DateCalendarIcon,
LazyImageWrapper, LazyImageWrapper,
@ -134,7 +134,7 @@ export default class EventMinimalistCard extends Vue {
<style lang="scss" scoped> <style lang="scss" scoped>
@use "@/styles/_mixins" as *; @use "@/styles/_mixins" as *;
@use "@/styles/_event-card"; @use "@/styles/_event-card";
@import "~bulma/sass/utilities/mixins.sass"; @import "../node_modules/bulma/sass/utilities/mixins.sass";
@import "@/variables.scss"; @import "@/variables.scss";
.event-minimalist-card-wrapper { .event-minimalist-card-wrapper {

View File

@ -253,7 +253,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop } from "vue-property-decorator"; import { Options, Prop } from "vue-property-decorator";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
import { RawLocation, Route } from "vue-router"; import { RawLocation, Route } from "vue-router";
@ -283,7 +283,7 @@ const defaultOptions: IEventCardOptions = {
memberofGroup: false, memberofGroup: false,
}; };
@Component({ @Options({
components: { components: {
DateCalendarIcon, DateCalendarIcon,
PopoverActorCard, PopoverActorCard,
@ -349,7 +349,7 @@ export default class EventParticipationCard extends mixins(
) { ) {
const organizerActor = participation.event.organizerActor as IPerson; const organizerActor = participation.event.organizerActor as IPerson;
await changeIdentity(this.$apollo.provider.defaultClient, organizerActor); await changeIdentity(this.$apollo.provider.defaultClient, organizerActor);
this.$buefy.notification.open({ this.$oruga.notification.open({
message: this.$t( message: this.$t(
"Current identity has been changed to {identityName} in order to manage this event.", "Current identity has been changed to {identityName} in order to manage this event.",
{ {
@ -396,7 +396,7 @@ export default class EventParticipationCard extends mixins(
<style lang="scss" scoped> <style lang="scss" scoped>
@use "@/styles/_mixins" as *; @use "@/styles/_mixins" as *;
@use "@/styles/_event-card"; @use "@/styles/_event-card";
@import "~bulma/sass/utilities/mixins.sass"; @import "../node_modules/bulma/sass/utilities/mixins.sass";
article.box { article.box {
div.tag-container { div.tag-container {

View File

@ -7,7 +7,7 @@
:message="fieldErrors" :message="fieldErrors"
:type="{ 'is-danger': fieldErrors.length }" :type="{ 'is-danger': fieldErrors.length }"
> >
<template slot="label"> <template #label>
{{ actualLabel }} {{ actualLabel }}
<span <span
class="is-size-6 has-text-weight-normal" class="is-size-6 has-text-weight-normal"
@ -103,19 +103,19 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Watch, Mixins } from "vue-property-decorator"; import { Options, Prop, Watch, mixins } from "vue-property-decorator";
import { LatLng } from "leaflet"; import { LatLng } from "leaflet";
import { Address, IAddress } from "../../types/address.model"; import { Address, IAddress } from "../../types/address.model";
import AddressAutoCompleteMixin from "../../mixins/AddressAutoCompleteMixin"; import AddressAutoCompleteMixin from "../../mixins/AddressAutoCompleteMixin";
import AddressInfo from "../../components/Address/AddressInfo.vue"; import AddressInfo from "../../components/Address/AddressInfo.vue";
@Component({ @Options({
inheritAttrs: false, inheritAttrs: false,
components: { components: {
AddressInfo, AddressInfo,
}, },
}) })
export default class FullAddressAutoComplete extends Mixins( export default class FullAddressAutoComplete extends mixins(
AddressAutoCompleteMixin AddressAutoCompleteMixin
) { ) {
@Prop({ required: false, default: "" }) label!: string; @Prop({ required: false, default: "" }) label!: string;

View File

@ -17,10 +17,10 @@
<script lang="ts"> <script lang="ts">
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import EventMinimalistCard from "./EventMinimalistCard.vue"; import EventMinimalistCard from "./EventMinimalistCard.vue";
@Component({ @Options({
components: { components: {
EventMinimalistCard, EventMinimalistCard,
}, },

View File

@ -12,9 +12,8 @@
<script lang="ts"> <script lang="ts">
import { IEventMetadataDescription } from "@/types/event-metadata"; import { IEventMetadataDescription } from "@/types/event-metadata";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class EtherpadIntegration extends Vue { export default class EtherpadIntegration extends Vue {
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true }) @Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
metadata!: IEventMetadataDescription; metadata!: IEventMetadataDescription;

View File

@ -12,9 +12,8 @@
<script lang="ts"> <script lang="ts">
import { IEventMetadataDescription } from "@/types/event-metadata"; import { IEventMetadataDescription } from "@/types/event-metadata";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class JitsiMeetIntegration extends Vue { export default class JitsiMeetIntegration extends Vue {
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true }) @Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
metadata!: IEventMetadataDescription; metadata!: IEventMetadataDescription;

View File

@ -15,9 +15,8 @@
<script lang="ts"> <script lang="ts">
import { IEventMetadataDescription } from "@/types/event-metadata"; import { IEventMetadataDescription } from "@/types/event-metadata";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class PeerTubeIntegration extends Vue { export default class PeerTubeIntegration extends Vue {
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true }) @Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
metadata!: IEventMetadataDescription; metadata!: IEventMetadataDescription;

View File

@ -16,9 +16,8 @@
<script lang="ts"> <script lang="ts">
import { IEventMetadataDescription } from "@/types/event-metadata"; import { IEventMetadataDescription } from "@/types/event-metadata";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class TwitchIntegration extends Vue { export default class TwitchIntegration extends Vue {
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true }) @Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
metadata!: IEventMetadataDescription; metadata!: IEventMetadataDescription;

View File

@ -16,9 +16,8 @@
<script lang="ts"> <script lang="ts">
import { IEventMetadataDescription } from "@/types/event-metadata"; import { IEventMetadataDescription } from "@/types/event-metadata";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
@Component
export default class YouTubeIntegration extends Vue { export default class YouTubeIntegration extends Vue {
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true }) @Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
metadata!: IEventMetadataDescription; metadata!: IEventMetadataDescription;

View File

@ -11,9 +11,9 @@
<script lang="ts"> <script lang="ts">
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import EventCard from "./EventCard.vue"; import EventCard from "./EventCard.vue";
@Component({ @Options({
components: { components: {
EventCard, EventCard,
}, },

View File

@ -12,10 +12,10 @@
<script lang="ts"> <script lang="ts">
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import EventMinimalistCard from "./EventMinimalistCard.vue"; import EventMinimalistCard from "./EventMinimalistCard.vue";
@Component({ @Options({
components: { components: {
EventMinimalistCard, EventMinimalistCard,
}, },

View File

@ -35,7 +35,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { IPerson, IActor, Actor } from "@/types/actor"; import { IPerson, IActor, Actor } from "@/types/actor";
import { import {
CURRENT_ACTOR_CLIENT, CURRENT_ACTOR_CLIENT,
@ -46,7 +46,7 @@ import { Paginate } from "@/types/paginate";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import { MemberRole } from "@/types/enums"; import { MemberRole } from "@/types/enums";
@Component({ @Options({
apollo: { apollo: {
groupMemberships: { groupMemberships: {
query: LOGGED_USER_MEMBERSHIPS, query: LOGGED_USER_MEMBERSHIPS,

View File

@ -118,7 +118,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import { Options, Prop, Vue, Watch } from "vue-property-decorator";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import { IActor, IGroup, IPerson, usernameWithDomain } from "../../types/actor"; import { IActor, IGroup, IPerson, usernameWithDomain } from "../../types/actor";
import OrganizerPicker from "./OrganizerPicker.vue"; import OrganizerPicker from "./OrganizerPicker.vue";
@ -138,7 +138,7 @@ const MEMBER_ROLES = [
MemberRole.MEMBER, MemberRole.MEMBER,
]; ];
@Component({ @Options({
components: { OrganizerPicker }, components: { OrganizerPicker },
apollo: { apollo: {
members: { members: {

View File

@ -1,28 +1,3 @@
import {EventJoinOptions} from "@/types/event.model";
<docs>
A button to set your participation
##### If the participant has been confirmed
```vue
<ParticipationButton :participation="{ role: 'PARTICIPANT' }" :currentActor="{ preferredUsername: 'test', avatar: { url: 'https://huit.re/EPX7vs1j' } }" />
```
##### If the participant has not being approved yet
```vue
<ParticipationButton :participation="{ role: 'NOT_APPROVED' }" :currentActor="{ preferredUsername: 'test', avatar: { url: 'https://huit.re/EPX7vs1j' } }" />
```
##### If the participant has been rejected
```vue
<ParticipationButton :participation="{ role: 'REJECTED' }" :currentActor="{ preferredUsername: 'test', avatar: { url: 'https://huit.re/EPX7vs1j' } }" />
```
##### If the participant doesn't exist yet
```vue
<ParticipationButton :participation="null" :currentActor="{ preferredUsername: 'test', avatar: { url: 'https://huit.re/EPX7vs1j' } }" />
```
</docs>
<template> <template>
<div class="participation-button"> <div class="participation-button">
<o-dropdown <o-dropdown
@ -61,13 +36,15 @@ A button to set your participation
position="is-bottom-left" position="is-bottom-left"
class="dropdown-disabled" class="dropdown-disabled"
> >
<button class="button is-success is-large" type="button" slot="trigger"> <template #trigger>
<o-icon icon="timer-sand-empty" /> <button class="button is-success is-large" type="button">
<template> <o-icon icon="timer-sand-empty" />
<span>{{ $t("I participate") }}</span> <template>
</template> <span>{{ $t("I participate") }}</span>
<o-icon icon="menu-down" /> </template>
</button> <o-icon icon="menu-down" />
</button>
</template>
<!-- <o-dropdown-item :value="false" aria-role="listitem">--> <!-- <o-dropdown-item :value="false" aria-role="listitem">-->
<!-- {{ $t('Change my identity…')}}--> <!-- {{ $t('Change my identity…')}}-->
@ -180,7 +157,7 @@ A button to set your participation
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { EventJoinOptions, ParticipantRole } from "@/types/enums"; import { EventJoinOptions, ParticipantRole } from "@/types/enums";
import { IParticipant } from "../../types/participant.model"; import { IParticipant } from "../../types/participant.model";
import { IEvent } from "../../types/event.model"; import { IEvent } from "../../types/event.model";
@ -191,7 +168,7 @@ import { CONFIG } from "../../graphql/config";
import { IConfig } from "../../types/config.model"; import { IConfig } from "../../types/config.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component({ @Options({
apollo: { apollo: {
currentUser: { currentUser: {
query: CURRENT_USER_CLIENT, query: CURRENT_USER_CLIENT,

View File

@ -14,10 +14,10 @@
<script lang="ts"> <script lang="ts">
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import { formatDistanceToNow } from "date-fns"; import { formatDistanceToNow } from "date-fns";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import EventCard from "./EventCard.vue"; import EventCard from "./EventCard.vue";
@Component({ @Options({
components: { components: {
EventCard, EventCard,
}, },

View File

@ -123,14 +123,14 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Ref } from "vue-property-decorator"; import { Options, Prop, Vue, Ref } from "vue-property-decorator";
import { EventStatus, EventVisibility } from "@/types/enums"; import { EventStatus, EventVisibility } from "@/types/enums";
import { IEvent } from "../../types/event.model"; import { IEvent } from "../../types/event.model";
import DiasporaLogo from "../Share/DiasporaLogo.vue"; import DiasporaLogo from "../Share/DiasporaLogo.vue";
import MastodonLogo from "../Share/MastodonLogo.vue"; import MastodonLogo from "../Share/MastodonLogo.vue";
import TelegramLogo from "../Share/TelegramLogo.vue"; import TelegramLogo from "../Share/TelegramLogo.vue";
@Component({ @Options({
components: { components: {
DiasporaLogo, DiasporaLogo,
MastodonLogo, MastodonLogo,

View File

@ -29,12 +29,12 @@
</o-field> </o-field>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import differenceBy from "lodash/differenceBy"; import differenceBy from "lodash/differenceBy";
import { ITag } from "../../types/tag.model"; import { ITag } from "../../types/tag.model";
import { FILTER_TAGS } from "@/graphql/tags"; import { FILTER_TAGS } from "@/graphql/tags";
@Component({ @Options({
apollo: { apollo: {
tags: { tags: {
query: FILTER_TAGS, query: FILTER_TAGS,

View File

@ -81,17 +81,16 @@
</footer> </footer>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator"; import { Vue, Watch } from "vue-property-decorator";
import { saveLocaleData } from "@/utils/auth"; import { saveLocaleData } from "@/utils/auth";
import { loadLanguageAsync } from "@/utils/i18n"; import { i18n, loadLanguageAsync } from "@/utils/i18n";
import RouteName from "../router/name"; import RouteName from "../router/name";
import langs from "../i18n/langs.json"; import langs from "../i18n/langs.json";
@Component
export default class Footer extends Vue { export default class Footer extends Vue {
RouteName = RouteName; RouteName = RouteName;
locale: string | null = this.$i18n.locale; locale: string | null = i18n.global.locale;
langs: Record<string, string> = langs; langs: Record<string, string> = langs;
@ -123,7 +122,7 @@ export default class Footer extends Vue {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "~bulma/sass/utilities/mixins.sass"; @import "../node_modules/bulma/sass/utilities/mixins.sass";
footer.footer { footer.footer {
color: $secondary; color: $secondary;
display: flex; display: flex;

View File

@ -56,13 +56,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { displayName, IGroup, usernameWithDomain } from "@/types/actor"; import { displayName, IGroup, usernameWithDomain } from "@/types/actor";
import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue"; import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import InlineAddress from "@/components/Address/InlineAddress.vue"; import InlineAddress from "@/components/Address/InlineAddress.vue";
@Component({ @Options({
components: { components: {
LazyImageWrapper, LazyImageWrapper,
InlineAddress, InlineAddress,

View File

@ -50,7 +50,9 @@
</div> </div>
<div> <div>
<o-dropdown aria-role="list" position="is-bottom-left"> <o-dropdown aria-role="list" position="is-bottom-left">
<o-icon icon="dots-horizontal" slot="trigger" /> <template #trigger>
<o-icon icon="dots-horizontal" />
</template>
<o-dropdown-item aria-role="listitem" @click="$emit('leave')"> <o-dropdown-item aria-role="listitem" @click="$emit('leave')">
<o-icon icon="exit-to-app" /> <o-icon icon="exit-to-app" />
@ -63,13 +65,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
import { displayNameAndUsername, usernameWithDomain } from "@/types/actor"; import { displayNameAndUsername, usernameWithDomain } from "@/types/actor";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import { MemberRole } from "@/types/enums"; import { MemberRole } from "@/types/enums";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component
export default class GroupMemberCard extends Vue { export default class GroupMemberCard extends Vue {
@Prop({ required: true }) member!: IMember; @Prop({ required: true }) member!: IMember;

View File

@ -17,10 +17,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Vue, Prop } from "vue-property-decorator";
import { Route } from "vue-router"; import { RouteLocationNormalizedLoaded } from "vue-router";
@Component
export default class GroupSection extends Vue { export default class GroupSection extends Vue {
@Prop({ required: true, type: String }) title!: string; @Prop({ required: true, type: String }) title!: string;
@ -29,7 +28,7 @@ export default class GroupSection extends Vue {
@Prop({ required: false, type: Boolean, default: true }) @Prop({ required: false, type: Boolean, default: true })
privateSection!: boolean; privateSection!: boolean;
@Prop({ required: true, type: Object }) route!: Route; @Prop({ required: true, type: Object }) route!: RouteLocationNormalizedLoaded;
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -70,12 +70,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
import { usernameWithDomain } from "@/types/actor"; import { usernameWithDomain } from "@/types/actor";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component
export default class InvitationCard extends Vue { export default class InvitationCard extends Vue {
@Prop({ required: true }) member!: IMember; @Prop({ required: true }) member!: IMember;

View File

@ -11,13 +11,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ACCEPT_INVITATION, REJECT_INVITATION } from "@/graphql/member"; import { ACCEPT_INVITATION, REJECT_INVITATION } from "@/graphql/member";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import InvitationCard from "@/components/Group/InvitationCard.vue"; import InvitationCard from "@/components/Group/InvitationCard.vue";
import { PERSON_STATUS_GROUP } from "@/graphql/actor"; import { PERSON_STATUS_GROUP } from "@/graphql/actor";
import { IMember } from "@/types/actor/member.model"; import { IMember } from "@/types/actor/member.model";
import { IGroup, IPerson, usernameWithDomain } from "@/types/actor"; import { IGroup, IPerson, usernameWithDomain } from "@/types/actor";
@Component({ @Options({
components: { components: {
InvitationCard, InvitationCard,
}, },

View File

@ -7,12 +7,12 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import RedirectWithAccount from "@/components/Utils/RedirectWithAccount.vue"; import RedirectWithAccount from "@/components/Utils/RedirectWithAccount.vue";
import { FETCH_GROUP } from "@/graphql/group"; import { FETCH_GROUP } from "@/graphql/group";
import { IGroup } from "@/types/actor"; import { IGroup } from "@/types/actor";
@Component({ @Options({
components: { RedirectWithAccount }, components: { RedirectWithAccount },
apollo: { apollo: {
group: { group: {

View File

@ -11,9 +11,9 @@
<script lang="ts"> <script lang="ts">
import { IGroup } from "@/types/actor"; import { IGroup } from "@/types/actor";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import GroupCard from "./GroupCard.vue"; import GroupCard from "./GroupCard.vue";
@Component({ @Options({
components: { components: {
GroupCard, GroupCard,
}, },

View File

@ -113,14 +113,14 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Ref } from "vue-property-decorator"; import { Options, Prop, Vue, Ref } from "vue-property-decorator";
import { GroupVisibility } from "@/types/enums"; import { GroupVisibility } from "@/types/enums";
import DiasporaLogo from "../Share/DiasporaLogo.vue"; import DiasporaLogo from "../Share/DiasporaLogo.vue";
import MastodonLogo from "../Share/MastodonLogo.vue"; import MastodonLogo from "../Share/MastodonLogo.vue";
import TelegramLogo from "../Share/MastodonLogo.vue"; import TelegramLogo from "../Share/MastodonLogo.vue";
import { displayName, IGroup } from "@/types/actor"; import { displayName, IGroup } from "@/types/actor";
@Component({ @Options({
components: { components: {
DiasporaLogo, DiasporaLogo,
MastodonLogo, MastodonLogo,

View File

@ -4,9 +4,8 @@
<script lang="ts"> <script lang="ts">
import { decode } from "blurhash"; import { decode } from "blurhash";
import { Component, Prop, Ref, Vue } from "vue-property-decorator"; import { Prop, Ref, Vue } from "vue-property-decorator";
@Component
export default class BlurhashImg extends Vue { export default class BlurhashImg extends Vue {
@Prop({ type: String, required: true }) hash!: string; @Prop({ type: String, required: true }) hash!: string;
@Prop({ type: Number, default: 1 }) aspectRatio!: string; @Prop({ type: Number, default: 1 }) aspectRatio!: string;

View File

@ -25,10 +25,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Prop, Component, Vue, Ref, Watch } from "vue-property-decorator"; import { Prop, Options, Vue, Ref, Watch } from "vue-property-decorator";
import BlurhashImg from "./BlurhashImg.vue"; import BlurhashImg from "./BlurhashImg.vue";
@Component({ @Options({
components: { components: {
BlurhashImg, BlurhashImg,
}, },

View File

@ -11,7 +11,7 @@
<script lang="ts"> <script lang="ts">
import { IMedia } from "@/types/media.model"; import { IMedia } from "@/types/media.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import LazyImage from "../Image/LazyImage.vue"; import LazyImage from "../Image/LazyImage.vue";
const DEFAULT_CARD_URL = "/img/mobilizon_default_card.png"; const DEFAULT_CARD_URL = "/img/mobilizon_default_card.png";
@ -27,7 +27,7 @@ const DEFAULT_PICTURE = {
}, },
}; };
@Component({ @Options({
components: { components: {
LazyImage, LazyImage,
}, },

View File

@ -28,13 +28,19 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { defineComponent } from "vue";
@Component export default defineComponent({
export default class Logo extends Vue { props: {
@Prop({ type: Boolean, required: false, default: false }) invert!: boolean; invert: {
} type: Boolean,
required: false,
default: false,
},
},
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
svg { svg {
fill: $background-color; fill: $background-color;

View File

@ -19,10 +19,10 @@
:zoomInTitle="$t('Zoom in')" :zoomInTitle="$t('Zoom in')"
:zoomOutTitle="$t('Zoom out')" :zoomOutTitle="$t('Zoom out')"
></l-control-zoom> ></l-control-zoom>
<v-locatecontrol <!-- <v-locatecontrol
v-if="canDoGeoLocation" v-if="canDoGeoLocation"
:options="{ icon: 'mdi mdi-map-marker' }" :options="{ icon: 'mdi mdi-map-marker' }"
/> /> -->
<l-marker <l-marker
:lat-lng="[lat, lon]" :lat-lng="[lat, lon]"
@add="openPopup" @add="openPopup"
@ -42,7 +42,7 @@
<script lang="ts"> <script lang="ts">
import { Icon, LatLng, LeafletMouseEvent, LeafletEvent } from "leaflet"; import { Icon, LatLng, LeafletMouseEvent, LeafletEvent } from "leaflet";
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { import {
LMap, LMap,
LTileLayer, LTileLayer,
@ -50,12 +50,12 @@ import {
LPopup, LPopup,
LIcon, LIcon,
LControlZoom, LControlZoom,
} from "vue2-leaflet"; } from "@vue-leaflet/vue-leaflet";
import Vue2LeafletLocateControl from "@/components/Map/Vue2LeafletLocateControl.vue"; // import Vue2LeafletLocateControl from "@/components/Map/Vue2LeafletLocateControl.vue";
import { CONFIG } from "../graphql/config"; import { CONFIG } from "../graphql/config";
import { IConfig } from "../types/config.model"; import { IConfig } from "../types/config.model";
@Component({ @Options({
components: { components: {
LTileLayer, LTileLayer,
LMap, LMap,
@ -63,7 +63,7 @@ import { IConfig } from "../types/config.model";
LPopup, LPopup,
LIcon, LIcon,
LControlZoom, LControlZoom,
"v-locatecontrol": Vue2LeafletLocateControl, // "v-locatecontrol": Vue2LeafletLocateControl,
}, },
apollo: { apollo: {
config: CONFIG, config: CONFIG,

View File

@ -11,11 +11,11 @@
*/ */
import { DomEvent } from "leaflet"; import { DomEvent } from "leaflet";
import { findRealParent, propsBinder } from "vue2-leaflet"; import { findRealParent, propsBinder } from "@vue-leaflet/vue-leaflet";
import Locatecontrol from "leaflet.locatecontrol"; import Locatecontrol from "leaflet.locatecontrol";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
@Component({ @Options({
beforeDestroy() { beforeDestroy() {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore

View File

@ -0,0 +1,381 @@
<template>
<o-navbar
id="navbar"
type="is-secondary"
wrapper-class="container"
:active.sync="mobileNavbarActive"
>
<template #brand>
<o-navbar-item
tag="router-link"
:to="{ name: RouteName.HOME }"
:aria-label="$t('Home')"
>
<logo />
</o-navbar-item>
</template>
<template #start>
<o-navbar-item tag="router-link" :to="{ name: RouteName.SEARCH }">{{
$t("Explore")
}}</o-navbar-item>
<o-navbar-item
v-if="currentActor.id && currentUser.isLoggedIn"
tag="router-link"
:to="{ name: RouteName.MY_EVENTS }"
>{{ $t("My events") }}</o-navbar-item
>
<o-navbar-item
tag="router-link"
:to="{ name: RouteName.MY_GROUPS }"
v-if="
config &&
config.features.groups &&
currentActor.id &&
currentUser.isLoggedIn
"
>{{ $t("My groups") }}</o-navbar-item
>
<o-navbar-item
tag="span"
v-if="
config &&
config.features.eventCreation &&
currentActor.id &&
currentUser.isLoggedIn
"
>
<o-button
v-if="!hideCreateEventsButton"
tag="router-link"
:to="{ name: RouteName.CREATE_EVENT }"
type="is-primary"
>{{ $t("Create") }}</o-button
>
</o-navbar-item>
<o-navbar-item
v-if="config && config.features.koenaConnect"
class="koena"
tag="a"
href="https://mediation.koena.net/framasoft/mobilizon/"
target="_blank"
rel="noopener external"
hreflang="fr"
>
<img
src="/img/koena-a11y.svg"
width="150"
alt="Contact accessibilité"
/>
</o-navbar-item>
</template>
<template #end>
<o-navbar-item tag="div">
<search-field @navbar-search="mobileNavbarActive = false" />
</o-navbar-item>
<o-navbar-dropdown
v-if="currentActor.id && currentUser.isLoggedIn"
right
collapsible
ref="user-dropdown"
tabindex="0"
tag="span"
@keyup.enter="toggleMenu"
>
<template #label v-if="currentActor">
<div class="identity-wrapper">
<div>
<figure class="image is-32x32" v-if="currentActor.avatar">
<img
class="is-rounded"
alt="avatarUrl"
:src="currentActor.avatar.url"
/>
</figure>
<o-icon v-else icon="account-circle" />
</div>
<div class="media-content is-hidden-desktop">
<span>{{ displayName(currentActor) }}</span>
<span class="has-text-grey-dark" v-if="currentActor.name"
>@{{ currentActor.preferredUsername }}</span
>
</div>
</div>
</template>
<!-- No identities dropdown if no identities -->
<span v-if="identities.length <= 1" />
<o-navbar-item
tag="span"
v-for="identity in identities"
v-else
:active="identity.id === currentActor.id"
:key="identity.id"
tabindex="0"
@click="setIdentity(identity)"
@keyup.enter="setIdentity(identity)"
>
<span>
<div class="media-left">
<figure class="image is-32x32" v-if="identity.avatar">
<img
class="is-rounded"
loading="lazy"
:src="identity.avatar.url"
alt
/>
</figure>
<o-icon v-else size="is-medium" icon="account-circle" />
</div>
<div class="media-content">
<span>{{ displayName(identity) }}</span>
<span class="has-text-grey-dark" v-if="identity.name"
>@{{ identity.preferredUsername }}</span
>
</div>
</span>
<hr class="navbar-divider" role="presentation" />
</o-navbar-item>
<o-navbar-item
tag="router-link"
:to="{ name: RouteName.UPDATE_IDENTITY }"
>{{ $t("My account") }}</o-navbar-item
>
<o-navbar-item
v-if="currentUser.role === ICurrentUserRole.ADMINISTRATOR"
tag="router-link"
:to="{ name: RouteName.ADMIN_DASHBOARD }"
>{{ $t("Administration") }}</o-navbar-item
>
<o-navbar-item
tag="span"
tabindex="0"
@click="logout"
@keyup.enter="logout"
>
<span>{{ $t("Log out") }}</span>
</o-navbar-item>
</o-navbar-dropdown>
<o-navbar-item v-else tag="div">
<div class="buttons">
<router-link
class="button is-primary"
v-if="config && config.registrationsOpen"
:to="{ name: RouteName.REGISTER }"
>
<strong>{{ $t("Sign up") }}</strong>
</router-link>
<router-link
class="button is-light"
:to="{ name: RouteName.LOGIN }"
>{{ $t("Log in") }}</router-link
>
</div>
</o-navbar-item>
</template>
</o-navbar>
</template>
<script lang="ts">
import Logo from "@/components/Logo.vue";
import { GraphQLError } from "graphql";
import { loadLanguageAsync } from "@/utils/i18n";
import { CURRENT_USER_CLIENT, USER_SETTINGS } from "../graphql/user";
import { changeIdentity, logout } from "../utils/auth";
import {
CURRENT_ACTOR_CLIENT,
IDENTITIES,
UPDATE_DEFAULT_ACTOR,
} from "../graphql/actor";
import { IPerson, Person } from "../types/actor";
import { CONFIG } from "../graphql/config";
import { IConfig } from "../types/config.model";
import { ICurrentUser, IUser } from "../types/current-user.model";
import SearchField from "./SearchField.vue";
import RouteName from "../router/name";
import { defineComponent } from "vue-demi";
import { useMutation, useQuery, useResult } from "@vue/apollo-composable";
import { ref } from "vue";
export default defineComponent({
name: "NavBar",
setup() {
const { result: resultCurrentUser } = useQuery(CURRENT_USER_CLIENT);
const currentUser =
useResult<{ currentUser: ICurrentUser }>(resultCurrentUser);
const { result: resultCurrentActor } = useQuery(CURRENT_ACTOR_CLIENT);
const currentActor =
useResult<{ currentUser: IPerson }>(resultCurrentActor);
const { mutate: updateDefaultActor } = useMutation(UPDATE_DEFAULT_ACTOR);
const { result: configResult } = useQuery(CONFIG);
const config = useResult<{ config: IConfig }>(configResult);
const { result: loggedUserResult } = useQuery(USER_SETTINGS);
const loggedUser = useResult<{ config: IUser }>(loggedUserResult);
const { result: identitiesResult } = useQuery(IDENTITIES);
const identities = useResult<{ identities: IPerson[] }, [], Person[]>(
identitiesResult,
[],
(data) => data.identities.map((identity: IPerson) => new Person(identity))
);
const mobileNavbarActive = false;
const userDropDown = ref(null) as any;
return {
currentUser,
currentActor,
config,
loggedUser,
identities,
mobileNavbarActive,
userDropDown,
updateDefaultActor,
};
},
components: {
Logo,
SearchField,
},
methods: {
toggleMenu(): void {
console.debug("called toggleMenu");
if (this.userDropDown) {
this.userDropDown.showMenu();
}
},
async handleErrors(errors: GraphQLError[]): Promise<void> {
if (
errors.length > 0 &&
errors[0].message ===
"You need to be logged-in to view your list of identities"
) {
await this.logout();
}
},
async logout(): Promise<void> {
await logout(this.$apollo.provider.defaultClient);
this.$oruga.notification.open({
message: this.$t("You have been disconnected") as string,
type: "is-success",
position: "is-bottom-right",
duration: 5000,
});
if (this.$route.name === RouteName.HOME) return;
await this.$router.push({ name: RouteName.HOME });
},
async setIdentity(identity: IPerson): Promise<void> {
await this.updateDefaultActor({
preferredUsername: identity.preferredUsername,
});
return changeIdentity(this.$apollo.provider.defaultClient, identity);
},
},
watch: {
async currentActor(): Promise<void> {
if (!this.currentUser?.isLoggedIn) return;
// If we don't have any identities, the user has validated their account,
// is logging for the first time but didn't create an identity somehow
if (this.identities?.length === 0) {
try {
await this.$router.push({
name: RouteName.REGISTER_PROFILE,
params: {
email: this.currentUser.email,
userAlreadyActivated: "true",
},
});
} catch (err) {
return undefined;
}
}
},
loggedUser(): void {
if (this.loggedUser?.locale) {
console.debug("Setting locale from navbar");
loadLanguageAsync(this.loggedUser.locale);
}
},
},
computed: {
hideCreateEventsButton(): boolean {
return !!this.config?.restrictions?.onlyGroupsCanCreateEvents;
},
},
});
</script>
<style lang="scss" scoped>
@use "@/styles/_mixins" as *;
nav {
.navbar-item {
a.button {
font-weight: bold;
}
svg {
height: 1.75rem;
}
}
.navbar-dropdown .navbar-item {
cursor: pointer;
span {
display: flex;
}
&.is-active {
background: $secondary;
}
span.icon.is-medium {
display: flex;
}
img {
max-height: 2.5em;
}
}
.navbar-item.has-dropdown a.navbar-link figure {
@include margin-right(0.75rem);
display: flex;
align-items: center;
}
a.navbar-item:focus-within {
background-color: inherit;
}
.koena {
padding-top: 0;
padding-bottom: 0;
& > img {
max-height: 4rem;
padding-top: 0.2rem;
}
}
.identity-wrapper {
display: flex;
.media-content span {
display: flex;
color: $violet-2;
}
}
}
</style>

View File

@ -1,185 +1,426 @@
<template> <template>
<o-navbar <nav class="bg-yellow-100 z-50">
id="navbar" <div class="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
type="is-secondary" <div class="relative flex items-center justify-between h-16">
wrapper-class="container" <div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
:active.sync="mobileNavbarActive" <!-- Mobile menu button-->
> <button
<template #brand> type="button"
<o-navbar-item class="
tag="router-link" inline-flex
:to="{ name: RouteName.HOME }" items-center
:aria-label="$t('Home')" justify-center
> p-2
<logo /> rounded-md
</o-navbar-item> text-gray-400
</template> hover:text-white hover:bg-yellow-400
<template #start> focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white
<o-navbar-item tag="router-link" :to="{ name: RouteName.SEARCH }">{{ "
$t("Explore") aria-controls="mobile-menu"
}}</o-navbar-item> aria-expanded="false"
<o-navbar-item >
v-if="currentActor.id && currentUser.isLoggedIn" <span class="sr-only">{{ $t("Open main menu") }}</span>
tag="router-link" <!--
:to="{ name: RouteName.MY_EVENTS }" Icon when menu is closed.
>{{ $t("My events") }}</o-navbar-item
>
<o-navbar-item
tag="router-link"
:to="{ name: RouteName.MY_GROUPS }"
v-if="
config &&
config.features.groups &&
currentActor.id &&
currentUser.isLoggedIn
"
>{{ $t("My groups") }}</o-navbar-item
>
<o-navbar-item
tag="span"
v-if="
config &&
config.features.eventCreation &&
currentActor.id &&
currentUser.isLoggedIn
"
>
<o-button
v-if="!hideCreateEventsButton"
tag="router-link"
:to="{ name: RouteName.CREATE_EVENT }"
type="is-primary"
>{{ $t("Create") }}</o-button
>
</o-navbar-item>
<o-navbar-item
v-if="config && config.features.koenaConnect"
class="koena"
tag="a"
href="https://mediation.koena.net/framasoft/mobilizon/"
target="_blank"
rel="noopener external"
hreflang="fr"
>
<img
src="/img/koena-a11y.svg"
width="150"
alt="Contact accessibilité"
/>
</o-navbar-item>
</template>
<template #end>
<o-navbar-item tag="div">
<search-field @navbar-search="mobileNavbarActive = false" />
</o-navbar-item>
<o-navbar-dropdown Heroicon name: outline/menu
v-if="currentActor.id && currentUser.isLoggedIn"
right Menu open: "hidden", Menu closed: "block"
collapsible -->
ref="user-dropdown" <svg
tabindex="0" class="block h-6 w-6"
tag="span" xmlns="http://www.w3.org/2000/svg"
@keyup.enter="toggleMenu" fill="none"
> viewBox="0 0 24 24"
<template #label v-if="currentActor"> stroke="currentColor"
<div class="identity-wrapper"> aria-hidden="true"
<div> >
<figure class="image is-32x32" v-if="currentActor.avatar"> <path
<img stroke-linecap="round"
class="is-rounded" stroke-linejoin="round"
alt="avatarUrl" stroke-width="2"
:src="currentActor.avatar.url" d="M4 6h16M4 12h16M4 18h16"
/> />
</figure> </svg>
<o-icon v-else icon="account-circle" /> <!--
</div> Icon when menu is open.
<div class="media-content is-hidden-desktop">
<span>{{ displayName(currentActor) }}</span> Heroicon name: outline/x
<span class="has-text-grey-dark" v-if="currentActor.name"
>@{{ currentActor.preferredUsername }}</span Menu open: "block", Menu closed: "hidden"
-->
<svg
class="hidden h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div
class="
flex-1 flex
items-center
justify-center
sm:items-stretch sm:justify-start
"
>
<div class="flex-shrink-0 flex items-center">
<img
class="block lg:hidden h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-mark-indigo-500.svg"
alt="Workflow"
/>
<router-link :to="{ name: RouteName.HOME }">
<logo class="hidden lg:block h-8 w-auto" />
</router-link>
</div>
<div class="hidden sm:block sm:ml-6">
<div class="flex items-center space-x-4">
<router-link
:to="{ name: RouteName.SEARCH }"
class="
text-gray-700
hover:bg-yellow-400 hover:text-black
px-3
py-2
rounded-md
text-sm
font-medium
"
>{{ $t("Explore") }}</router-link
> >
<router-link
:to="{ name: RouteName.MY_EVENTS }"
v-if="currentActor.id && currentUser.isLoggedIn"
class="
text-gray-700
hover:bg-yellow-400 hover:text-black
px-3
py-2
rounded-md
text-sm
font-medium
"
>{{ $t("My events") }}</router-link
>
<router-link
:to="{ name: RouteName.MY_GROUPS }"
v-if="
config &&
config.features.groups &&
currentActor.id &&
currentUser.isLoggedIn
"
class="
text-gray-700
hover:bg-yellow-400 hover:text-black
px-3
py-2
rounded-md
text-sm
font-medium
"
>{{ $t("My groups") }}</router-link
>
<router-link
v-if="!hideCreateEventsButton"
:to="{ name: RouteName.CREATE_EVENT }"
class="
p-2
pl-5
pr-5
transition-colors
duration-700
transform
bg-indigo-500
hover:bg-blue-400
text-gray-100
rounded-lg
focus:border-4
border-indigo-300
"
>
{{ $t("Create") }}
</router-link>
<a
v-if="config && config.features.koenaConnect"
class="koena"
href="https://mediation.koena.net/framasoft/mobilizon/"
target="_blank"
rel="noopener external"
hreflang="fr"
>
<img
src="/img/koena-a11y.svg"
width="150"
alt="Contact accessibilité"
/>
</a>
</div> </div>
</div> </div>
</template>
<!-- No identities dropdown if no identities -->
<span v-if="identities.length <= 1" />
<o-navbar-item
tag="span"
v-for="identity in identities"
v-else
:active="identity.id === currentActor.id"
:key="identity.id"
tabindex="0"
@click="setIdentity(identity)"
@keyup.enter="setIdentity(identity)"
>
<span>
<div class="media-left">
<figure class="image is-32x32" v-if="identity.avatar">
<img
class="is-rounded"
loading="lazy"
:src="identity.avatar.url"
alt
/>
</figure>
<o-icon v-else size="is-medium" icon="account-circle" />
</div>
<div class="media-content">
<span>{{ displayName(identity) }}</span>
<span class="has-text-grey-dark" v-if="identity.name"
>@{{ identity.preferredUsername }}</span
>
</div>
</span>
<hr class="navbar-divider" role="presentation" />
</o-navbar-item>
<o-navbar-item
tag="router-link"
:to="{ name: RouteName.UPDATE_IDENTITY }"
>{{ $t("My account") }}</o-navbar-item
>
<o-navbar-item
v-if="currentUser.role === ICurrentUserRole.ADMINISTRATOR"
tag="router-link"
:to="{ name: RouteName.ADMIN_DASHBOARD }"
>{{ $t("Administration") }}</o-navbar-item
>
<o-navbar-item
tag="span"
tabindex="0"
@click="logout"
@keyup.enter="logout"
>
<span>{{ $t("Log out") }}</span>
</o-navbar-item>
</o-navbar-dropdown>
<o-navbar-item v-else tag="div">
<div class="buttons">
<router-link
class="button is-primary"
v-if="config && config.registrationsOpen"
:to="{ name: RouteName.REGISTER }"
>
<strong>{{ $t("Sign up") }}</strong>
</router-link>
<router-link
class="button is-light"
:to="{ name: RouteName.LOGIN }"
>{{ $t("Log in") }}</router-link
>
</div> </div>
</o-navbar-item> <div
</template> class="
</o-navbar> absolute
inset-y-0
right-0
flex
items-center
pr-2
sm:static sm:inset-auto sm:ml-6 sm:pr-0
"
>
<div>
<search-field @navbar-search="mobileNavbarActive = false" />
</div>
<!-- Profile dropdown -->
<div class="ml-3 relative">
<div>
<button
type="button"
class="
bg-gray-800
flex
text-sm
rounded-full
focus:outline-none
focus:ring-2
focus:ring-offset-2
focus:ring-offset-gray-800
focus:ring-white
"
id="user-menu-button"
aria-expanded="false"
aria-haspopup="true"
@click="toggleMenu"
>
<span class="sr-only">{{ $t("Open user menu") }}</span>
<img
v-if="currentActor.avatar"
class="h-8 w-8 rounded-full"
:src="currentActor.avatar.url"
alt=""
/>
<o-icon v-else icon="account-circle" />
</button>
</div>
<!--
Dropdown menu, show/hide based on menu state.
Entering: "transition ease-out duration-100"
From: "transform opacity-0 scale-95"
To: "transform opacity-100 scale-100"
Leaving: "transition ease-in duration-75"
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
<div
v-show="userDropDownOpened"
class="
origin-top-right
absolute
right-0
mt-2
w-48
rounded-md
shadow-lg
py-1
bg-white
ring-1 ring-black ring-opacity-5
focus:outline-none
"
role="menu"
aria-orientation="vertical"
aria-labelledby="user-menu-button"
tabindex="-1"
>
<button
v-for="identity in identities"
:active="identity.id === currentActor.id"
:key="identity.id"
@click="setIdentity(identity)"
@keyup.enter="setIdentity(identity)"
class="
block
px-4
py-2
text-sm text-gray-700
hover:bg-yellow-400 hover:text-black
w-full
"
role="menuitem"
tabindex="-1"
id="user-menu-item-2"
>
<div class="flex text-left">
<div>
<div
v-if="identity.avatar"
class="
rounded-full
h-8
w-8
bg-gray-500
flex
items-center
justify-center
overflow-hidden
"
>
<img :src="identity.avatar.url" alt="" />
</div>
<o-icon v-else size="is-medium" icon="account-circle" />
</div>
<div class="flex flex-col">
<span class="ml-2 font-bold text-sm">{{
displayName(identity)
}}</span>
<span
class="ml-2 text-sm text-gray-600 dark:text-gray-400"
v-if="identity.name"
>@{{ identity.preferredUsername }}</span
>
</div>
</div>
</button>
<!-- Active: "bg-gray-100", Not Active: "" -->
<router-link
:to="{ name: RouteName.UPDATE_IDENTITY }"
class="
block
px-4
py-2
text-sm text-gray-700
hover:bg-yellow-400 hover:text-black
"
role="menuitem"
tabindex="-1"
id="user-menu-item-0"
>{{ $t("My account") }}</router-link
>
<router-link
v-if="currentUser.role === ICurrentUserRole.ADMINISTRATOR"
:to="{ name: RouteName.ADMIN_DASHBOARD }"
class="
block
px-4
py-2
text-sm text-gray-700
hover:bg-yellow-400 hover:text-black
"
role="menuitem"
tabindex="-1"
id="user-menu-item-1"
>{{ $t("Administration") }}</router-link
>
<button
@click="logout"
@keyup.enter="logout"
class="
block
px-4
py-2
text-sm text-gray-700
hover:bg-yellow-400 hover:text-black
text-left
w-full
"
role="menuitem"
tabindex="-1"
id="user-menu-item-2"
>
{{ $t("Log out") }}
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Mobile menu, show/hide based on menu state. -->
<div class="sm:hidden" id="mobile-menu">
<div class="px-2 pt-2 pb-3 space-y-1">
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
<a
href="#"
class="
bg-gray-900
text-white
block
px-3
py-2
rounded-md
text-base
font-medium
"
aria-current="page"
>Dashboard</a
>
<a
href="#"
class="
text-gray-300
hover:bg-gray-700 hover:text-white
block
px-3
py-2
rounded-md
text-base
font-medium
"
>Team</a
>
<a
href="#"
class="
text-gray-300
hover:bg-gray-700 hover:text-white
block
px-3
py-2
rounded-md
text-base
font-medium
"
>Projects</a
>
<a
href="#"
class="
text-gray-300
hover:bg-gray-700 hover:text-white
block
px-3
py-2
rounded-md
text-base
font-medium
"
>Calendar</a
>
</div>
</div>
</nav>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -193,15 +434,21 @@ import {
IDENTITIES, IDENTITIES,
UPDATE_DEFAULT_ACTOR, UPDATE_DEFAULT_ACTOR,
} from "../graphql/actor"; } from "../graphql/actor";
import { IPerson, Person } from "../types/actor"; import { displayName, IPerson, Person } from "../types/actor";
import { CONFIG } from "../graphql/config"; import { CONFIG } from "../graphql/config";
import { IConfig } from "../types/config.model"; import { IConfig } from "../types/config.model";
import { ICurrentUser, IUser } from "../types/current-user.model"; import { ICurrentUser, IUser } from "../types/current-user.model";
import SearchField from "./SearchField.vue"; import SearchField from "./SearchField.vue";
import RouteName from "../router/name"; import RouteName from "../router/name";
import { defineComponent } from "vue-demi"; import { defineComponent } from "vue-demi";
import { useQuery, useResult } from "@vue/apollo-composable"; import {
useApolloClient,
useMutation,
useQuery,
useResult,
} from "@vue/apollo-composable";
import { ref } from "vue"; import { ref } from "vue";
import { ICurrentUserRole } from "@/types/enums";
export default defineComponent({ export default defineComponent({
name: "NavBar", name: "NavBar",
@ -214,6 +461,8 @@ export default defineComponent({
const currentActor = const currentActor =
useResult<{ currentUser: IPerson }>(resultCurrentActor); useResult<{ currentUser: IPerson }>(resultCurrentActor);
const { mutate: updateDefaultActor } = useMutation(UPDATE_DEFAULT_ACTOR);
const { result: configResult } = useQuery(CONFIG); const { result: configResult } = useQuery(CONFIG);
const config = useResult<{ config: IConfig }>(configResult); const config = useResult<{ config: IConfig }>(configResult);
@ -229,7 +478,9 @@ export default defineComponent({
const mobileNavbarActive = false; const mobileNavbarActive = false;
const userDropDown = ref(null) as any; const userDropDownOpened = ref(false);
const { resolveClient } = useApolloClient();
return { return {
currentUser, currentUser,
@ -238,7 +489,12 @@ export default defineComponent({
loggedUser, loggedUser,
identities, identities,
mobileNavbarActive, mobileNavbarActive,
userDropDown, userDropDownOpened,
updateDefaultActor,
RouteName,
displayName,
ICurrentUserRole,
resolveClient,
}; };
}, },
components: { components: {
@ -247,10 +503,7 @@ export default defineComponent({
}, },
methods: { methods: {
toggleMenu(): void { toggleMenu(): void {
console.debug("called toggleMenu"); this.userDropDownOpened = !this.userDropDownOpened;
if (this.userDropDown) {
this.userDropDown.showMenu();
}
}, },
async handleErrors(errors: GraphQLError[]): Promise<void> { async handleErrors(errors: GraphQLError[]): Promise<void> {
if ( if (
@ -262,52 +515,41 @@ export default defineComponent({
} }
}, },
async logout(): Promise<void> { async logout(): Promise<void> {
await logout(this.$apollo.provider.defaultClient); await logout(this.resolveClient());
this.$oruga.notification.open({ // this.$oruga.notification.open({
message: this.$t("You have been disconnected") as string, // message: this.$t("You have been disconnected") as string,
type: "is-success", // type: "is-success",
position: "is-bottom-right", // position: "is-bottom-right",
duration: 5000, // duration: 5000,
}); // });
if (this.$route.name === RouteName.HOME) return; if (this.$route.name === RouteName.HOME) return;
await this.$router.push({ name: RouteName.HOME }); await this.$router.push({ name: RouteName.HOME });
}, },
async setIdentity(identity: IPerson): Promise<void> { async setIdentity(identity: IPerson): Promise<void> {
await this.$apollo.mutate({ await this.updateDefaultActor({
mutation: UPDATE_DEFAULT_ACTOR, preferredUsername: identity.preferredUsername,
variables: {
preferredUsername: identity.preferredUsername,
},
}); });
return changeIdentity(this.$apollo.provider.defaultClient, identity); return changeIdentity(this.resolveClient(), identity);
}, },
}, },
watch: { watch: {
async currentActor(): Promise<void> { async currentActor(): Promise<void> {
if (!this.currentUser?.isLoggedIn) return; if (!this.currentUser?.isLoggedIn) return;
const { data } = await this.$apollo.query<{ identities: IPerson[] }>({
query: IDENTITIES,
});
if (data) {
this.identities = data.identities.map(
(identity: IPerson) => new Person(identity)
);
// If we don't have any identities, the user has validated their account, // If we don't have any identities, the user has validated their account,
// is logging for the first time but didn't create an identity somehow // is logging for the first time but didn't create an identity somehow
if (this.identities.length === 0) { if (this.identities?.length === 0) {
try { try {
await this.$router.push({ await this.$router.push({
name: RouteName.REGISTER_PROFILE, name: RouteName.REGISTER_PROFILE,
params: { params: {
email: this.currentUser.email, email: this.currentUser.email,
userAlreadyActivated: "true", userAlreadyActivated: "true",
}, },
}); });
} catch (err) { } catch (err) {
return undefined; return undefined;
}
} }
} }
}, },

View File

@ -64,14 +64,14 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { confirmLocalAnonymousParticipation } from "@/services/AnonymousParticipationStorage"; import { confirmLocalAnonymousParticipation } from "@/services/AnonymousParticipationStorage";
import { EventJoinOptions } from "@/types/enums"; import { EventJoinOptions } from "@/types/enums";
import { IParticipant } from "../../types/participant.model"; import { IParticipant } from "../../types/participant.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import { CONFIRM_PARTICIPATION } from "../../graphql/event"; import { CONFIRM_PARTICIPATION } from "../../graphql/event";
@Component({ @Options({
metaInfo() { metaInfo() {
return { return {
title: this.$t("Confirm participation") as string, title: this.$t("Confirm participation") as string,

View File

@ -120,7 +120,7 @@
<script lang="ts"> <script lang="ts">
import { EventJoinOptions, EventStatus, ParticipantRole } from "@/types/enums"; import { EventJoinOptions, EventStatus, ParticipantRole } from "@/types/enums";
import { IParticipant } from "@/types/participant.model"; import { IParticipant } from "@/types/participant.model";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import RouteName from "@/router/name"; import RouteName from "@/router/name";
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
@ -133,7 +133,7 @@ import {
} from "@/services/AnonymousParticipationStorage"; } from "@/services/AnonymousParticipationStorage";
import ParticipationButton from "../Event/ParticipationButton.vue"; import ParticipationButton from "../Event/ParticipationButton.vue";
@Component({ @Options({
apollo: { apollo: {
currentActor: CURRENT_ACTOR_CLIENT, currentActor: CURRENT_ACTOR_CLIENT,
config: CONFIG, config: CONFIG,

View File

@ -7,12 +7,12 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import RedirectWithAccount from "@/components/Utils/RedirectWithAccount.vue"; import RedirectWithAccount from "@/components/Utils/RedirectWithAccount.vue";
import { FETCH_EVENT } from "@/graphql/event"; import { FETCH_EVENT } from "@/graphql/event";
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
@Component({ @Options({
components: { RedirectWithAccount }, components: { RedirectWithAccount },
apollo: { apollo: {
event: { event: {

View File

@ -125,7 +125,7 @@
</section> </section>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { EventModel, IEvent } from "@/types/event.model"; import { EventModel, IEvent } from "@/types/event.model";
import { FETCH_EVENT_BASIC, JOIN_EVENT } from "@/graphql/event"; import { FETCH_EVENT_BASIC, JOIN_EVENT } from "@/graphql/event";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
@ -136,7 +136,7 @@ import RouteName from "@/router/name";
import { IParticipant } from "../../types/participant.model"; import { IParticipant } from "../../types/participant.model";
import { ApolloCache, FetchResult } from "@apollo/client/core"; import { ApolloCache, FetchResult } from "@apollo/client/core";
@Component({ @Options({
apollo: { apollo: {
event: { event: {
query: FETCH_EVENT_BASIC, query: FETCH_EVENT_BASIC,

View File

@ -99,7 +99,7 @@
</section> </section>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { FETCH_EVENT } from "@/graphql/event"; import { FETCH_EVENT } from "@/graphql/event";
import EventListViewCard from "@/components/Event/EventListViewCard.vue"; import EventListViewCard from "@/components/Event/EventListViewCard.vue";
import { EventModel, IEvent } from "@/types/event.model"; import { EventModel, IEvent } from "@/types/event.model";
@ -109,7 +109,7 @@ import { IConfig } from "@/types/config.model";
import Subtitle from "@/components/Utils/Subtitle.vue"; import Subtitle from "@/components/Utils/Subtitle.vue";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component({ @Options({
components: { components: {
VerticalDivider, VerticalDivider,
EventListViewCard, EventListViewCard,

View File

@ -112,9 +112,8 @@ figure.image {
<script lang="ts"> <script lang="ts">
import { IMedia } from "@/types/media.model"; import { IMedia } from "@/types/media.model";
import { Component, Model, Prop, Vue, Watch } from "vue-property-decorator"; import { Model, Prop, Vue, Watch } from "vue-property-decorator";
@Component
export default class PictureUpload extends Vue { export default class PictureUpload extends Vue {
@Model("change", { type: File }) readonly pictureFile!: File; @Model("change", { type: File }) readonly pictureFile!: File;

View File

@ -11,10 +11,10 @@
<script lang="ts"> <script lang="ts">
import { IPost } from "@/types/post.model"; import { IPost } from "@/types/post.model";
import { PropType } from "vue"; import { PropType } from "vue";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import PostListItem from "./PostListItem.vue"; import PostListItem from "./PostListItem.vue";
@Component({ @Options({
components: { components: {
PostListItem, PostListItem,
}, },

View File

@ -42,13 +42,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { formatDistanceToNow, subWeeks, isBefore } from "date-fns"; import { formatDistanceToNow, subWeeks, isBefore } from "date-fns";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import { IPost } from "../../types/post.model"; import { IPost } from "../../types/post.model";
import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue"; import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
import { displayName } from "@/types/actor"; import { displayName } from "@/types/actor";
@Component({ @Options({
components: { components: {
LazyImageWrapper, LazyImageWrapper,
}, },
@ -75,7 +75,7 @@ export default class PostListItem extends Vue {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@use "@/styles/_mixins" as *; @use "@/styles/_mixins" as *;
@import "~bulma/sass/utilities/mixins.sass"; @import "../node_modules/bulma/sass/utilities/mixins.sass";
.post-minimalist-card-wrapper { .post-minimalist-card-wrapper {
display: grid; display: grid;

View File

@ -113,7 +113,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Ref } from "vue-property-decorator"; import { Options, Prop, Vue, Ref } from "vue-property-decorator";
import { PostVisibility } from "@/types/enums"; import { PostVisibility } from "@/types/enums";
import { IPost } from "../../types/post.model"; import { IPost } from "../../types/post.model";
import DiasporaLogo from "../Share/DiasporaLogo.vue"; import DiasporaLogo from "../Share/DiasporaLogo.vue";
@ -122,7 +122,7 @@ import TelegramLogo from "../Share/TelegramLogo.vue";
import { PropType } from "vue"; import { PropType } from "vue";
import RouteName from "@/router/name"; import RouteName from "@/router/name";
@Component({ @Options({
components: { components: {
DiasporaLogo, DiasporaLogo,
MastodonLogo, MastodonLogo,

View File

@ -1,8 +1,3 @@
<docs>
```vue
<report-card :report="{ reported: { name: 'Some bad guy', preferredUsername: 'kevin' }, reporter: { preferredUsername: 'somePerson34' }, reportContent: 'This is not good'}" />
```
</docs>
<template> <template>
<div class="card" v-if="report"> <div class="card" v-if="report">
<div class="card-content"> <div class="card-content">
@ -42,11 +37,10 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
import { IReport } from "@/types/report.model"; import { IReport } from "@/types/report.model";
import { ActorType } from "@/types/enums"; import { ActorType } from "@/types/enums";
@Component
export default class ReportCard extends Vue { export default class ReportCard extends Vue {
@Prop({ required: true }) report!: IReport; @Prop({ required: true }) report!: IReport;

View File

@ -90,10 +90,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { IComment } from "../../types/comment.model"; import { IComment } from "../../types/comment.model";
@Component({ @Options({
mounted() { mounted() {
this.$data.isActive = true; this.$data.isActive = true;
}, },

View File

@ -37,21 +37,21 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Mixins, Prop } from "vue-property-decorator"; import { Options, mixins, Prop } from "vue-property-decorator";
import { Route } from "vue-router";
import Draggable, { ChangeEvent } from "vuedraggable"; import Draggable, { ChangeEvent } from "vuedraggable";
import { SnackbarProgrammatic as Snackbar } from "buefy"; // import { SnackbarProgrammatic as Snackbar } from "buefy";
import { IResource } from "../../types/resource"; import { IResource } from "../../types/resource";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import ResourceMixin from "../../mixins/resource"; import ResourceMixin from "../../mixins/resource";
import { IGroup, usernameWithDomain } from "../../types/actor"; import { IGroup, usernameWithDomain } from "../../types/actor";
import ResourceDropdown from "./ResourceDropdown.vue"; import ResourceDropdown from "./ResourceDropdown.vue";
import { UPDATE_RESOURCE } from "../../graphql/resources"; import { UPDATE_RESOURCE } from "../../graphql/resources";
import { NavigationFailure } from "vue-router";
@Component({ @Options({
components: { Draggable, ResourceDropdown }, components: { Draggable, ResourceDropdown },
}) })
export default class FolderItem extends Mixins(ResourceMixin) { export default class FolderItem extends mixins(ResourceMixin) {
@Prop({ required: true, type: Object }) resource!: IResource; @Prop({ required: true, type: Object }) resource!: IResource;
@Prop({ required: true, type: Object }) group!: IGroup; @Prop({ required: true, type: Object }) group!: IGroup;
@ -72,7 +72,9 @@ export default class FolderItem extends Mixins(ResourceMixin) {
usernameWithDomain = usernameWithDomain; usernameWithDomain = usernameWithDomain;
async onChange(evt: ChangeEvent<IResource>): Promise<Route | undefined> { async onChange(
evt: ChangeEvent<IResource>
): Promise<NavigationFailure | void | undefined> {
if (evt.added && evt.added.element) { if (evt.added && evt.added.element) {
const movedResource = evt.added.element as IResource; const movedResource = evt.added.element as IResource;
const updatedResource = await this.moveResource(movedResource); const updatedResource = await this.moveResource(movedResource);
@ -111,11 +113,11 @@ export default class FolderItem extends Mixins(ResourceMixin) {
} }
return data.updateResource; return data.updateResource;
} catch (e: any) { } catch (e: any) {
Snackbar.open({ // Snackbar.open({
message: e.message, // message: e.message,
type: "is-danger", // type: "is-danger",
position: "is-bottom", // position: "is-bottom",
}); // });
return undefined; return undefined;
} }
} }

View File

@ -17,8 +17,7 @@
</o-dropdown> </o-dropdown>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-property-decorator"; import { Vue } from "vue-property-decorator";
@Component
export default class ResourceDropdown extends Vue {} export default class ResourceDropdown extends Vue {}
</script> </script>

View File

@ -53,11 +53,11 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import { IResource, mapServiceTypeToIcon } from "@/types/resource"; import { IResource, mapServiceTypeToIcon } from "@/types/resource";
import ResourceDropdown from "@/components/Resource/ResourceDropdown.vue"; import ResourceDropdown from "@/components/Resource/ResourceDropdown.vue";
@Component({ @Options({
components: { ResourceDropdown }, components: { ResourceDropdown },
}) })
export default class ResourceItem extends Vue { export default class ResourceItem extends Vue {

View File

@ -89,11 +89,11 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Options, Vue, Prop } from "vue-property-decorator";
import { GET_RESOURCE } from "../../graphql/resources"; import { GET_RESOURCE } from "../../graphql/resources";
import { IResource } from "../../types/resource"; import { IResource } from "../../types/resource";
@Component({ @Options({
apollo: { apollo: {
resource: { resource: {
query: GET_RESOURCE, query: GET_RESOURCE,

View File

@ -1,42 +1,78 @@
<template> <template>
<label for="navSearchField"> <div class="flex relative mx-auto w-full max-w-md">
<span class="visually-hidden">{{ defaultPlaceHolder }}</span> <label for="navSearchField" class="sr-only">{{ defaultPlaceHolder }}</label>
<o-input <input
custom-class="searchField" class="
id="navSearchField" border-2 border-primary
icon="magnify" bg-red
transition
h-12
px-5
pr-16
rounded-md
focus:outline-none
w-full
text-black text-lg
"
type="search" type="search"
rounded name="search"
id="navSearchField"
dir="auto" dir="auto"
:placeholder="defaultPlaceHolder" :placeholder="defaultPlaceHolder"
v-model="search" v-model="search"
@keyup.native.enter="enter" @keyup.enter="enter"
/> />
</label> <button type="submit" class="absolute right-2 top-3 mr-4">
<svg
class="text-black h-6 w-4 fill-current"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 56.966 56.966"
style="enable-background: new 0 0 56.966 56.966"
xml:space="preserve"
width="512px"
height="512px"
>
<path
d="M55.146,51.887L41.588,37.786c3.486-4.144,5.396-9.358,5.396-14.786c0-12.682-10.318-23-23-23s-23,10.318-23,23 s10.318,23,23,23c4.761,0,9.298-1.436,13.177-4.162l13.661,14.208c0.571,0.593,1.339,0.92,2.162,0.92 c0.779,0,1.518-0.297,2.079-0.837C56.255,54.982,56.293,53.08,55.146,51.887z M23.984,6c9.374,0,17,7.626,17,17s-7.626,17-17,17 s-17-7.626-17-17S14.61,6,23.984,6z"
/>
</svg>
</button>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { defineComponent } from "vue";
import { useI18n } from "vue-i18n";
import RouteName from "../router/name"; import RouteName from "../router/name";
@Component export default defineComponent({
export default class SearchField extends Vue { props: {
@Prop({ type: String, required: false }) placeholder!: string; placeholder: {
required: false,
type: String,
},
},
setup(props) {
const search = "";
const { t } = useI18n({ useScope: "global" });
search = ""; const defaultPlaceHolder = props.placeholder || t("Search");
return { search, defaultPlaceHolder };
async enter(): Promise<void> { },
this.$emit("navbar-search"); methods: {
await this.$router.push({ async enter(): Promise<void> {
name: RouteName.SEARCH, this.$emit("navbar-search");
query: { term: this.search }, await this.$router.push({
}); name: RouteName.SEARCH,
} query: { term: this.search },
});
get defaultPlaceHolder(): string { },
// We can't use "this" inside @Prop's default value. },
return this.placeholder || (this.$t("Search") as string); });
}
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -40,12 +40,10 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component } from "vue-property-decorator"; // import { SnackbarProgrammatic as Snackbar } from "buefy";
import { SnackbarProgrammatic as Snackbar } from "buefy"; import { mixins } from "vue-property-decorator";
import { mixins } from "vue-class-component";
import Onboarding from "../../mixins/onboarding"; import Onboarding from "../../mixins/onboarding";
@Component
export default class NotificationsOnboarding extends mixins(Onboarding) { export default class NotificationsOnboarding extends mixins(Onboarding) {
notificationOnDay = true; notificationOnDay = true;
@ -61,11 +59,11 @@ export default class NotificationsOnboarding extends mixins(Onboarding) {
try { try {
this.doUpdateSetting(variables); this.doUpdateSetting(variables);
} catch (e: any) { } catch (e: any) {
Snackbar.open({ // Snackbar.open({
message: e.message, // message: e.message,
type: "is-danger", // type: "is-danger",
position: "is-bottom", // position: "is-bottom",
}); // });
} }
} }
} }

View File

@ -7,14 +7,13 @@
</li> </li>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Prop, Vue } from "vue-property-decorator";
import { Route } from "vue-router"; import { RouteLocationNormalizedLoaded } from "vue-router";
@Component
export default class SettingMenuItem extends Vue { export default class SettingMenuItem extends Vue {
@Prop({ required: false, type: String }) title!: string; @Prop({ required: false, type: String }) title!: string;
@Prop({ required: true, type: Object }) to!: Route; @Prop({ required: true, type: Object }) to!: RouteLocationNormalizedLoaded;
get isActive(): boolean { get isActive(): boolean {
if (!this.to) return false; if (!this.to) return false;

View File

@ -8,11 +8,11 @@
</li> </li>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Options, Prop, Vue } from "vue-property-decorator";
import SettingMenuItem from "@/components/Settings/SettingMenuItem.vue"; import SettingMenuItem from "@/components/Settings/SettingMenuItem.vue";
import { Route } from "vue-router"; import { Route } from "vue-router";
@Component({ @Options({
components: { SettingMenuItem }, components: { SettingMenuItem },
}) })
export default class SettingMenuSection extends Vue { export default class SettingMenuSection extends Vue {

Some files were not shown because too many files have changed in this diff Show More