parent
32a63a693d
commit
dccf397df5
|
@ -15,13 +15,7 @@ config :mobilizon, Mobilizon.Web.Endpoint,
|
|||
check_origin: false,
|
||||
watchers: [
|
||||
node: [
|
||||
"node_modules/webpack/bin/webpack.js",
|
||||
"--mode",
|
||||
"development",
|
||||
"--watch",
|
||||
"--watch-options-stdin",
|
||||
"--config",
|
||||
"node_modules/@vue/cli-service/webpack.config.js",
|
||||
"node_modules/.bin/vite",
|
||||
cd: Path.expand("../js", __DIR__)
|
||||
]
|
||||
]
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
"version": "2.0.0-beta.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"dev": "tsc --noEmit && vite",
|
||||
"serve": "vite preview",
|
||||
"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:e2e": "vue-cli-service test:e2e",
|
||||
"lint": "vue-cli-service lint",
|
||||
"build:assets": "vue-cli-service build",
|
||||
"build:assets": "vite build",
|
||||
"build:pictures": "bash ./scripts/build/pictures.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -18,6 +19,7 @@
|
|||
"@mdi/font": "^6.1.95",
|
||||
"@oruga-ui/oruga-next": "^0.4.7",
|
||||
"@oruga-ui/theme-bulma": "^0.1.3",
|
||||
"@popperjs/core": "^2.10.2",
|
||||
"@tiptap/core": "^2.0.0-beta.41",
|
||||
"@tiptap/extension-blockquote": "^2.0.0-beta.6",
|
||||
"@tiptap/extension-bubble-menu": "^2.0.0-beta.9",
|
||||
|
@ -31,13 +33,16 @@
|
|||
"@tiptap/extension-underline": "^2.0.0-beta.7",
|
||||
"@tiptap/starter-kit": "^2.0.0-beta.37",
|
||||
"@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/skip-to": "^3.0.3",
|
||||
"@vue-leaflet/vue-leaflet": "^0.6.1",
|
||||
"@vue/apollo-composable": "^4.0.0-alpha.15",
|
||||
"@vue/apollo-option": "^4.0.0-alpha.15",
|
||||
"apollo-absinthe-upload-link": "^1.5.0",
|
||||
"blurhash": "^1.1.3",
|
||||
"body-scroll-lock": "^4.0.0-beta.0",
|
||||
"bulma": "^0.9.3",
|
||||
"bulma-divider": "^0.2.0",
|
||||
"core-js": "^3.6.4",
|
||||
"date-fns": "^2.16.0",
|
||||
|
@ -67,11 +72,14 @@
|
|||
"vuedraggable": "^2.24.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@originjs/vite-plugin-commonjs": "^1.0.1",
|
||||
"@rollup/plugin-dynamic-import-vars": "^1.4.1",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/leaflet": "^1.5.2",
|
||||
"@types/leaflet.locatecontrol": "^0.60.7",
|
||||
"@types/lodash": "^4.14.141",
|
||||
"@types/ngeohash": "^0.6.2",
|
||||
"@types/node": "^16.11.7",
|
||||
"@types/phoenix": "^1.5.2",
|
||||
"@types/prosemirror-inputrules": "^1.0.2",
|
||||
"@types/prosemirror-model": "^1.7.2",
|
||||
|
@ -80,18 +88,12 @@
|
|||
"@types/sanitize-html": "^2.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
||||
"@typescript-eslint/parser": "^5.3.0",
|
||||
"@vue/cli-plugin-babel": "~5.0.0-rc.1",
|
||||
"@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",
|
||||
"@vitejs/plugin-vue": "^1.9.4",
|
||||
"@vue/compiler-sfc": "^3.1.0",
|
||||
"@vue/eslint-config-typescript": "^9.0.0",
|
||||
"@vue/test-utils": "^2.0.0-rc.16",
|
||||
"@vue/vue3-jest": "^27.0.0-alpha.3",
|
||||
"autoprefixer": "^10.4.0",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"cypress": "^8.3.0",
|
||||
"eslint": "^8.2.0",
|
||||
|
@ -104,12 +106,17 @@
|
|||
"jest": "^27.1.0",
|
||||
"jest-junit": "^13.0.0",
|
||||
"mock-apollo-client": "^1.1.0",
|
||||
"postcss": "^8.3.11",
|
||||
"prettier": "^2.2.1",
|
||||
"prettier-eslint": "^13.0.0",
|
||||
"sass": "^1.34.1",
|
||||
"sass": "^1.43.4",
|
||||
"sass-loader": "^12.0.0",
|
||||
"tailwindcss": "^2.2.19",
|
||||
"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",
|
||||
"webpack-cli": "^4.7.0"
|
||||
}
|
||||
|
|
|
@ -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 |
|
@ -1,22 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<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>
|
||||
<noscript>
|
||||
<strong
|
||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||
<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="/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
|
||||
continue.</strong
|
||||
>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<main id="main" v-else>
|
||||
<transition name="fade" mode="out-in">
|
||||
<!-- <router-view ref="routerView" /> -->
|
||||
<router-view ref="routerView" />
|
||||
</transition>
|
||||
</main>
|
||||
<mobilizon-footer />
|
||||
|
@ -53,7 +53,12 @@ import { ICurrentUser } from "./types/current-user.model";
|
|||
import jwt_decode, { JwtPayload } from "jwt-decode";
|
||||
import { refreshAccessToken } from "./apollo/utils";
|
||||
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 { useAnnouncer } from "@vue-a11y/announcer";
|
||||
import { useMeta } from "vue-meta";
|
||||
|
@ -76,6 +81,8 @@ export default defineComponent({
|
|||
|
||||
useMeta({ titleTemplate: "%s | Mobilizon" });
|
||||
|
||||
const { resolveClient } = useApolloClient();
|
||||
|
||||
return {
|
||||
config,
|
||||
currentUser,
|
||||
|
@ -83,6 +90,7 @@ export default defineComponent({
|
|||
online: false,
|
||||
interval,
|
||||
routerView,
|
||||
resolveClient,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
|
@ -91,11 +99,6 @@ export default defineComponent({
|
|||
import(/* webpackChunkName: "editor" */ "./components/Error.vue"),
|
||||
"mobilizon-footer": Footer,
|
||||
},
|
||||
async created(): Promise<void> {
|
||||
if (await this.initializeCurrentUser()) {
|
||||
await initializeCurrentActor(this.$apollo.provider.defaultClient);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async initializeCurrentUser(): Promise<boolean> {
|
||||
const userId = localStorage.getItem(AUTH_USER_ID);
|
||||
|
@ -145,7 +148,10 @@ export default defineComponent({
|
|||
return document.title;
|
||||
},
|
||||
},
|
||||
mounted(): void {
|
||||
async mounted(): Promise<void> {
|
||||
if (await this.initializeCurrentUser()) {
|
||||
await initializeCurrentActor(this.resolveClient());
|
||||
}
|
||||
this.online = window.navigator.onLine;
|
||||
window.addEventListener("offline", () => {
|
||||
this.online = false;
|
||||
|
@ -192,7 +198,7 @@ export default defineComponent({
|
|||
token?.exp !== undefined &&
|
||||
new Date(token.exp * 1000 - 60000) < new Date()
|
||||
) {
|
||||
refreshAccessToken(this.$apollo.getClient());
|
||||
refreshAccessToken(this.resolveClient());
|
||||
}
|
||||
}
|
||||
}, 60000);
|
||||
|
@ -237,7 +243,7 @@ export default defineComponent({
|
|||
|
||||
/* Icons */
|
||||
$mdi-font-path: "~@mdi/font/fonts";
|
||||
@import "~@mdi/font/scss/materialdesignicons";
|
||||
@import "../node_modules/@mdi/font/scss/materialdesignicons";
|
||||
@import "common";
|
||||
|
||||
#mobilizon {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
@use "@/styles/_mixins" as *;
|
||||
@import "variables.scss";
|
||||
|
||||
@import "~bulma";
|
||||
@import "~bulma-divider";
|
||||
@import "~buefy/src/scss/buefy";
|
||||
// @import "../node_modules/bulma/bulma.sass";
|
||||
// @import "../node_modules/bulma-divider/dist/css/bulma-divider.sass";
|
||||
// @import "~buefy/src/scss/buefy";
|
||||
@import "styles/vue-announcer.scss";
|
||||
@import "styles/vue-skip-to.scss";
|
||||
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
</p>
|
||||
</template>
|
||||
<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 {
|
||||
@Prop({ required: true, type: String }) contact!: string;
|
||||
|
||||
|
|
|
@ -36,15 +36,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template slot="footer">
|
||||
<span class="has-text-grey" v-show="page > totalPages">
|
||||
Thats it! No more movies found.
|
||||
</span>
|
||||
</template>
|
||||
</o-autocomplete>
|
||||
</template>
|
||||
<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 { IPerson } from "@/types/actor";
|
||||
import { SEARCH_PERSONS } from "@/graphql/search";
|
||||
|
@ -52,7 +47,6 @@ import { Paginate } from "@/types/paginate";
|
|||
|
||||
const SEARCH_PERSON_LIMIT = 10;
|
||||
|
||||
@Component
|
||||
export default class ActorAutoComplete extends Vue {
|
||||
@Model("change", { type: Object }) readonly defaultSelected!: IPerson | null;
|
||||
|
||||
|
|
|
@ -24,10 +24,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||
import { Vue, Prop } from "vue-property-decorator";
|
||||
import { IActor, usernameWithDomain } from "../../types/actor";
|
||||
|
||||
@Component
|
||||
export default class ActorCard extends Vue {
|
||||
@Prop({ required: true, type: Object }) actor!: IActor;
|
||||
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||
import { Vue, Prop } from "vue-property-decorator";
|
||||
import { IActor, usernameWithDomain } from "../../types/actor";
|
||||
|
||||
@Component
|
||||
export default class ActorInline extends Vue {
|
||||
@Prop({ required: true, type: Object }) actor!: IActor;
|
||||
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
</template>
|
||||
|
||||
<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 { IPerson, Person } from "../../types/actor";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
identities: {
|
||||
query: IDENTITIES,
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
</template>
|
||||
<script lang="ts">
|
||||
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 ActorCard from "./ActorCard.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
ActorCard,
|
||||
},
|
||||
|
|
|
@ -53,9 +53,9 @@ import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
|
|||
import { CONFIG } from "@/graphql/config";
|
||||
import { IPerson } from "@/types/actor";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { Options, Vue } from "vue-property-decorator";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
config: CONFIG,
|
||||
currentActor: CURRENT_ACTOR_CLIENT,
|
||||
|
|
|
@ -54,13 +54,13 @@
|
|||
<script lang="ts">
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import { ActivityDiscussionSubject } from "@/types/enums";
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { Options } from "vue-property-decorator";
|
||||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PopoverActorCard,
|
||||
},
|
||||
|
|
|
@ -40,12 +40,12 @@ import {
|
|||
ActivityEventSubject,
|
||||
} from "@/types/enums";
|
||||
import { mixins } from "vue-class-component";
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { Options } from "vue-property-decorator";
|
||||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PopoverActorCard,
|
||||
},
|
||||
|
|
|
@ -72,13 +72,13 @@
|
|||
<script lang="ts">
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
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 PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PopoverActorCard,
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<script lang="ts">
|
||||
import { displayName } from "@/types/actor";
|
||||
import { ActivityMemberSubject, MemberRole } from "@/types/enums";
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { Options } from "vue-property-decorator";
|
||||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
|
@ -44,7 +44,7 @@ export const MEMBER_ROLE_VALUE: Record<string, number> = {
|
|||
[MemberRole.CREATOR]: 100,
|
||||
};
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PopoverActorCard,
|
||||
},
|
||||
|
|
|
@ -36,13 +36,13 @@
|
|||
<script lang="ts">
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import { ActivityPostSubject } from "@/types/enums";
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { Options } from "vue-property-decorator";
|
||||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PopoverActorCard,
|
||||
},
|
||||
|
|
|
@ -46,14 +46,14 @@
|
|||
<script lang="ts">
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import { ActivityResourceSubject } from "@/types/enums";
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { Options } from "vue-property-decorator";
|
||||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
import { Location } from "vue-router";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PopoverActorCard,
|
||||
},
|
||||
|
|
|
@ -44,9 +44,8 @@
|
|||
<script lang="ts">
|
||||
import { IAddress } from "@/types/address.model";
|
||||
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 {
|
||||
@Prop({ required: true, type: Object as PropType<IAddress> })
|
||||
address!: IAddress;
|
||||
|
|
|
@ -20,9 +20,8 @@
|
|||
<script lang="ts">
|
||||
import { IAddress } from "@/types/address.model";
|
||||
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 {
|
||||
@Prop({ required: true, type: Object as PropType<IAddress> })
|
||||
physicalAddress!: IAddress;
|
||||
|
|
|
@ -128,8 +128,8 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Mixins } from "vue-property-decorator";
|
||||
import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { Options, mixins } from "vue-property-decorator";
|
||||
// import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import {
|
||||
ACCEPT_RELAY,
|
||||
|
@ -143,7 +143,7 @@ import { Paginate } from "@/types/paginate";
|
|||
|
||||
const FOLLOWERS_PER_PAGE = 10;
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
relayFollowers: {
|
||||
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;
|
||||
|
||||
formatDistanceToNow = formatDistanceToNow;
|
||||
|
@ -211,11 +211,11 @@ export default class Followers extends Mixins(RelayMixin) {
|
|||
this.checkedRows = [];
|
||||
} catch (e: any) {
|
||||
if (e.message) {
|
||||
Snackbar.open({
|
||||
message: e.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
// Snackbar.open({
|
||||
// message: e.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,11 +232,11 @@ export default class Followers extends Mixins(RelayMixin) {
|
|||
this.checkedRows = [];
|
||||
} catch (e: any) {
|
||||
if (e.message) {
|
||||
Snackbar.open({
|
||||
message: e.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
// Snackbar.open({
|
||||
// message: e.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,8 +138,8 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Mixins } from "vue-property-decorator";
|
||||
import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { Options, mixins } from "vue-property-decorator";
|
||||
// import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin";
|
||||
import { IFollower } from "../../types/actor/follower.model";
|
||||
|
@ -152,7 +152,7 @@ import gql from "graphql-tag";
|
|||
|
||||
const FOLLOWINGS_PER_PAGE = 10;
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
relayFollowings: {
|
||||
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 = "";
|
||||
|
||||
RelayMixin = RelayMixin;
|
||||
|
@ -256,11 +256,11 @@ export default class Followings extends Mixins(RelayMixin) {
|
|||
this.newRelayAddress = "";
|
||||
} catch (err: any) {
|
||||
if (err.message) {
|
||||
Snackbar.open({
|
||||
message: err.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
// Snackbar.open({
|
||||
// message: err.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -179,9 +179,9 @@
|
|||
</li>
|
||||
</template>
|
||||
<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 { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
// import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import { CommentModeration } from "@/types/enums";
|
||||
import { CommentModel, IComment } from "../../types/comment.model";
|
||||
|
@ -193,7 +193,7 @@ import { IReport } from "../../types/report.model";
|
|||
import { CREATE_REPORT } from "../../graphql/report";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
currentActor: {
|
||||
query: CURRENT_ACTOR_CLIENT,
|
||||
|
@ -295,7 +295,7 @@ export default class Comment extends Vue {
|
|||
|
||||
reportModal(): void {
|
||||
if (!this.comment.actor) return;
|
||||
this.$buefy.modal.open({
|
||||
this.$oruga.modal.open({
|
||||
parent: this,
|
||||
component: ReportModal,
|
||||
props: {
|
||||
|
@ -324,7 +324,7 @@ export default class Comment extends Vue {
|
|||
forward,
|
||||
},
|
||||
});
|
||||
this.$buefy.notification.open({
|
||||
this.$oruga.notification.open({
|
||||
message: this.$t("Comment from @{username} reported", {
|
||||
username: this.comment.actor.preferredUsername,
|
||||
}) as string,
|
||||
|
@ -334,11 +334,11 @@ export default class Comment extends Vue {
|
|||
});
|
||||
} catch (e: any) {
|
||||
if (e.message) {
|
||||
Snackbar.open({
|
||||
message: e.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
// Snackbar.open({
|
||||
// message: e.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
</template>
|
||||
|
||||
<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 IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
|
||||
import { CommentModeration } from "@/types/enums";
|
||||
|
@ -101,7 +101,7 @@ import { IEvent } from "../../types/event.model";
|
|||
import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core";
|
||||
import EmptyContent from "@/components/Utils/EmptyContent.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
currentActor: CURRENT_ACTOR_CLIENT,
|
||||
comments: {
|
||||
|
@ -366,7 +366,7 @@ export default class CommentTree extends Vue {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/_mixins" as *;
|
||||
@import "~bulma/sass/utilities/mixins.sass";
|
||||
@import "../node_modules/bulma/sass/utilities/mixins.sass";
|
||||
form.new-comment {
|
||||
padding-bottom: 1rem;
|
||||
|
||||
|
|
|
@ -109,13 +109,13 @@
|
|||
</article>
|
||||
</template>
|
||||
<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 { IComment } from "../../types/comment.model";
|
||||
import { usernameWithDomain, IPerson } from "../../types/actor";
|
||||
import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
currentActor: CURRENT_ACTOR_CLIENT,
|
||||
},
|
||||
|
|
|
@ -50,12 +50,11 @@
|
|||
</router-link>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Prop, Vue } from "vue-property-decorator";
|
||||
import { formatDistanceToNowStrict } from "date-fns";
|
||||
import { IDiscussion } from "../../types/discussions";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component
|
||||
export default class DiscussionListItem extends Vue {
|
||||
@Prop({ required: true, type: Object }) discussion!: IDiscussion;
|
||||
|
||||
|
|
|
@ -193,8 +193,8 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
|
||||
import { Editor, EditorContent, BubbleMenu } from "@tiptap/vue-2";
|
||||
import { Options, Prop, Vue, Watch } from "vue-property-decorator";
|
||||
import { Editor, EditorContent, BubbleMenu } from "@tiptap/vue-3";
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import Document from "@tiptap/extension-document";
|
||||
import Paragraph from "@tiptap/extension-paragraph";
|
||||
|
@ -214,7 +214,7 @@ import CharacterCount from "@tiptap/extension-character-count";
|
|||
import { AutoDir } from "./Editor/Autodir";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: { EditorContent, BubbleMenu },
|
||||
apollo: {
|
||||
currentActor: {
|
||||
|
@ -319,17 +319,17 @@ export default class EditorComponent extends Vue {
|
|||
* Show a popup to get the link from the URL
|
||||
*/
|
||||
showLinkMenu(): void {
|
||||
this.$buefy.dialog.prompt({
|
||||
message: this.$t("Enter the link URL") as string,
|
||||
inputAttrs: {
|
||||
type: "url",
|
||||
},
|
||||
trapFocus: true,
|
||||
onConfirm: (value) => {
|
||||
if (!this.editor) return undefined;
|
||||
this.editor.chain().focus().setLink({ href: value }).run();
|
||||
},
|
||||
});
|
||||
// this.$buefy.dialog.prompt({
|
||||
// message: this.$t("Enter the link URL") as string,
|
||||
// inputAttrs: {
|
||||
// type: "url",
|
||||
// },
|
||||
// trapFocus: true,
|
||||
// onConfirm: (value) => {
|
||||
// if (!this.editor) return undefined;
|
||||
// this.editor.chain().focus().setLink({ href: value }).run();
|
||||
// },
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { UPLOAD_MEDIA } from "@/graphql/upload";
|
||||
import apolloProvider from "@/vue-apollo";
|
||||
import { apolloClient } from "@/vue-apollo";
|
||||
import { ApolloClient } from "@apollo/client/core/ApolloClient";
|
||||
import { Plugin } from "prosemirror-state";
|
||||
import { EditorView } from "prosemirror-view";
|
||||
|
@ -61,7 +61,7 @@ const CustomImage = Image.extend({
|
|||
});
|
||||
if (!coordinates) return false;
|
||||
const client =
|
||||
apolloProvider.defaultClient as ApolloClient<NormalizedCacheObject>;
|
||||
apolloClient as ApolloClient<NormalizedCacheObject>;
|
||||
|
||||
try {
|
||||
images.forEach(async (image) => {
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import { SEARCH_PERSONS } from "@/graphql/search";
|
||||
import { VueRenderer } from "@tiptap/vue-2";
|
||||
import { VueRenderer } from "@tiptap/vue-3";
|
||||
import tippy from "tippy.js";
|
||||
import MentionList from "./MentionList.vue";
|
||||
import { ApolloClient } from "@apollo/client/core/ApolloClient";
|
||||
import apolloProvider from "@/vue-apollo";
|
||||
import { apolloClient } from "@/vue-apollo";
|
||||
import { IPerson } from "@/types/actor";
|
||||
import pDebounce from "p-debounce";
|
||||
import { NormalizedCacheObject } from "@apollo/client/cache/inmemory/types";
|
||||
|
||||
const client =
|
||||
apolloProvider.defaultClient as ApolloClient<NormalizedCacheObject>;
|
||||
const client = apolloClient as ApolloClient<NormalizedCacheObject>;
|
||||
|
||||
const fetchItems = async (query: string): Promise<IPerson[]> => {
|
||||
const result = await client.query({
|
||||
|
@ -43,6 +42,8 @@ const mentionOptions: Partial<any> = {
|
|||
return {
|
||||
onStart: (props: any) => {
|
||||
component = new VueRenderer(MentionList, {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
parent: this,
|
||||
propsData: props,
|
||||
});
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
</template>
|
||||
|
||||
<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 { IPerson } from "@/types/actor";
|
||||
import ActorCard from "../../components/Account/ActorCard.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
ActorCard,
|
||||
},
|
||||
|
|
|
@ -118,9 +118,9 @@
|
|||
</template>
|
||||
<script lang="ts">
|
||||
import { CONTACT } from "@/graphql/config";
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Options, Prop, Vue } from "vue-property-decorator";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
config: {
|
||||
query: CONTACT,
|
||||
|
|
|
@ -59,14 +59,14 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 AddressAutoCompleteMixin from "@/mixins/AddressAutoCompleteMixin";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
export default class AddressAutoComplete extends Mixins(
|
||||
export default class AddressAutoComplete extends mixins(
|
||||
AddressAutoCompleteMixin
|
||||
) {
|
||||
@Prop({ required: false, default: false }) type!: string | false;
|
||||
|
|
|
@ -1,16 +1,3 @@
|
|||
<docs>
|
||||
### Example
|
||||
```vue
|
||||
<DateCalendarIcon date="2019-10-05T18:41:11.720Z" />
|
||||
```
|
||||
|
||||
```vue
|
||||
<DateCalendarIcon
|
||||
:date="new Date()"
|
||||
/>
|
||||
```
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="datetime-container"
|
||||
|
@ -25,9 +12,8 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 {
|
||||
/**
|
||||
* `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;
|
||||
|
||||
get dateObj(): Date {
|
||||
return new Date(this.$props.date);
|
||||
return new Date(this.date);
|
||||
}
|
||||
|
||||
get month(): string {
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
<script lang="ts">
|
||||
import { IMedia } from "@/types/media.model";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
LazyImageWrapper,
|
||||
},
|
||||
|
|
|
@ -92,7 +92,7 @@ import {
|
|||
organizerDisplayName,
|
||||
organizer,
|
||||
} 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 LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
|
||||
import { Actor, Person } from "@/types/actor";
|
||||
|
@ -100,7 +100,7 @@ import { EventStatus, ParticipantRole } from "@/types/enums";
|
|||
import RouteName from "../../router/name";
|
||||
import InlineAddress from "@/components/Address/InlineAddress.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DateCalendarIcon,
|
||||
LazyImageWrapper,
|
||||
|
|
|
@ -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>
|
||||
<p v-if="!endsOn">
|
||||
<span>{{
|
||||
|
@ -112,9 +93,8 @@
|
|||
</template>
|
||||
<script lang="ts">
|
||||
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 {
|
||||
@Prop({ required: true }) beginsOn!: string;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
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 { IPerson, usernameWithDomain } from "@/types/actor";
|
||||
import { mixins } from "vue-class-component";
|
||||
|
@ -93,7 +93,7 @@ const defaultOptions: IEventCardOptions = {
|
|||
memberofGroup: false,
|
||||
};
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DateCalendarIcon,
|
||||
},
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
import { Address, IAddress } from "@/types/address.model";
|
||||
import { RoutingTransportationType, RoutingType } from "@/types/enums";
|
||||
import { PropType } from "vue";
|
||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||
import { Options, Vue, Prop } from "vue-property-decorator";
|
||||
|
||||
const RoutingParamType = {
|
||||
[RoutingType.OPENSTREETMAP]: {
|
||||
|
@ -87,7 +87,7 @@ const RoutingParamType = {
|
|||
},
|
||||
};
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
"map-leaflet": () =>
|
||||
import(/* webpackChunkName: "map" */ "../../components/Map.vue"),
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 {
|
||||
@Prop({ required: false, type: String }) icon!: string;
|
||||
|
||||
|
|
|
@ -83,9 +83,8 @@
|
|||
import { EventMetadataKeyType, EventMetadataType } from "@/types/enums";
|
||||
import { IEventMetadataDescription } from "@/types/event-metadata";
|
||||
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 {
|
||||
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
|
||||
value!: IEventMetadataDescription;
|
||||
|
|
|
@ -99,7 +99,7 @@ import {
|
|||
} from "@/types/event-metadata";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
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 { eventMetaDataList } from "../../services/EventMetadata";
|
||||
import { EventMetadataCategories, EventMetadataType } from "@/types/enums";
|
||||
|
@ -109,7 +109,7 @@ type GroupedIEventMetadata = Array<{
|
|||
items: IEventMetadata[];
|
||||
}>;
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
EventMetadataItem,
|
||||
},
|
||||
|
|
|
@ -141,7 +141,7 @@ import { IConfig } from "@/types/config.model";
|
|||
import { EventMetadataKeyType, EventMetadataType } from "@/types/enums";
|
||||
import { IEvent } from "@/types/event.model";
|
||||
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 { usernameWithDomain } from "../../types/actor";
|
||||
import EventMetadataBlock from "./EventMetadataBlock.vue";
|
||||
|
@ -156,7 +156,7 @@ import {
|
|||
import { eventMetaDataList } from "../../services/EventMetadata";
|
||||
import { IUser } from "@/types/current-user.model";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
EventMetadataBlock,
|
||||
EventFullDate,
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
</router-link>
|
||||
</template>
|
||||
<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 DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
|
||||
import { ParticipantRole } from "@/types/enums";
|
||||
|
@ -110,7 +110,7 @@ import RouteName from "../../router/name";
|
|||
import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
|
||||
import InlineAddress from "@/components/Address/InlineAddress.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DateCalendarIcon,
|
||||
LazyImageWrapper,
|
||||
|
@ -134,7 +134,7 @@ export default class EventMinimalistCard extends Vue {
|
|||
<style lang="scss" scoped>
|
||||
@use "@/styles/_mixins" as *;
|
||||
@use "@/styles/_event-card";
|
||||
@import "~bulma/sass/utilities/mixins.sass";
|
||||
@import "../node_modules/bulma/sass/utilities/mixins.sass";
|
||||
@import "@/variables.scss";
|
||||
|
||||
.event-minimalist-card-wrapper {
|
||||
|
|
|
@ -253,7 +253,7 @@
|
|||
</template>
|
||||
|
||||
<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 { mixins } from "vue-class-component";
|
||||
import { RawLocation, Route } from "vue-router";
|
||||
|
@ -283,7 +283,7 @@ const defaultOptions: IEventCardOptions = {
|
|||
memberofGroup: false,
|
||||
};
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DateCalendarIcon,
|
||||
PopoverActorCard,
|
||||
|
@ -349,7 +349,7 @@ export default class EventParticipationCard extends mixins(
|
|||
) {
|
||||
const organizerActor = participation.event.organizerActor as IPerson;
|
||||
await changeIdentity(this.$apollo.provider.defaultClient, organizerActor);
|
||||
this.$buefy.notification.open({
|
||||
this.$oruga.notification.open({
|
||||
message: this.$t(
|
||||
"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>
|
||||
@use "@/styles/_mixins" as *;
|
||||
@use "@/styles/_event-card";
|
||||
@import "~bulma/sass/utilities/mixins.sass";
|
||||
@import "../node_modules/bulma/sass/utilities/mixins.sass";
|
||||
|
||||
article.box {
|
||||
div.tag-container {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:message="fieldErrors"
|
||||
:type="{ 'is-danger': fieldErrors.length }"
|
||||
>
|
||||
<template slot="label">
|
||||
<template #label>
|
||||
{{ actualLabel }}
|
||||
<span
|
||||
class="is-size-6 has-text-weight-normal"
|
||||
|
@ -103,19 +103,19 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 { Address, IAddress } from "../../types/address.model";
|
||||
import AddressAutoCompleteMixin from "../../mixins/AddressAutoCompleteMixin";
|
||||
import AddressInfo from "../../components/Address/AddressInfo.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
inheritAttrs: false,
|
||||
components: {
|
||||
AddressInfo,
|
||||
},
|
||||
})
|
||||
export default class FullAddressAutoComplete extends Mixins(
|
||||
export default class FullAddressAutoComplete extends mixins(
|
||||
AddressAutoCompleteMixin
|
||||
) {
|
||||
@Prop({ required: false, default: "" }) label!: string;
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
<script lang="ts">
|
||||
import { IEvent } from "@/types/event.model";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
EventMinimalistCard,
|
||||
},
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
<script lang="ts">
|
||||
import { IEventMetadataDescription } from "@/types/event-metadata";
|
||||
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 {
|
||||
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
|
||||
metadata!: IEventMetadataDescription;
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
<script lang="ts">
|
||||
import { IEventMetadataDescription } from "@/types/event-metadata";
|
||||
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 {
|
||||
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
|
||||
metadata!: IEventMetadataDescription;
|
||||
|
|
|
@ -15,9 +15,8 @@
|
|||
<script lang="ts">
|
||||
import { IEventMetadataDescription } from "@/types/event-metadata";
|
||||
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 {
|
||||
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
|
||||
metadata!: IEventMetadataDescription;
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
<script lang="ts">
|
||||
import { IEventMetadataDescription } from "@/types/event-metadata";
|
||||
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 {
|
||||
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
|
||||
metadata!: IEventMetadataDescription;
|
||||
|
|
|
@ -16,9 +16,8 @@
|
|||
<script lang="ts">
|
||||
import { IEventMetadataDescription } from "@/types/event-metadata";
|
||||
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 {
|
||||
@Prop({ type: Object as PropType<IEventMetadataDescription>, required: true })
|
||||
metadata!: IEventMetadataDescription;
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<script lang="ts">
|
||||
import { IEvent } from "@/types/event.model";
|
||||
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";
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
EventCard,
|
||||
},
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
<script lang="ts">
|
||||
import { IEvent } from "@/types/event.model";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
EventMinimalistCard,
|
||||
},
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 {
|
||||
CURRENT_ACTOR_CLIENT,
|
||||
|
@ -46,7 +46,7 @@ import { Paginate } from "@/types/paginate";
|
|||
import { IMember } from "@/types/actor/member.model";
|
||||
import { MemberRole } from "@/types/enums";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
groupMemberships: {
|
||||
query: LOGGED_USER_MEMBERSHIPS,
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 { IActor, IGroup, IPerson, usernameWithDomain } from "../../types/actor";
|
||||
import OrganizerPicker from "./OrganizerPicker.vue";
|
||||
|
@ -138,7 +138,7 @@ const MEMBER_ROLES = [
|
|||
MemberRole.MEMBER,
|
||||
];
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: { OrganizerPicker },
|
||||
apollo: {
|
||||
members: {
|
||||
|
|
|
@ -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>
|
||||
<div class="participation-button">
|
||||
<o-dropdown
|
||||
|
@ -61,13 +36,15 @@ A button to set your participation
|
|||
position="is-bottom-left"
|
||||
class="dropdown-disabled"
|
||||
>
|
||||
<button class="button is-success is-large" type="button" slot="trigger">
|
||||
<o-icon icon="timer-sand-empty" />
|
||||
<template>
|
||||
<span>{{ $t("I participate") }}</span>
|
||||
</template>
|
||||
<o-icon icon="menu-down" />
|
||||
</button>
|
||||
<template #trigger>
|
||||
<button class="button is-success is-large" type="button">
|
||||
<o-icon icon="timer-sand-empty" />
|
||||
<template>
|
||||
<span>{{ $t("I participate") }}</span>
|
||||
</template>
|
||||
<o-icon icon="menu-down" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<!-- <o-dropdown-item :value="false" aria-role="listitem">-->
|
||||
<!-- {{ $t('Change my identity…')}}-->
|
||||
|
@ -180,7 +157,7 @@ A button to set your participation
|
|||
</template>
|
||||
|
||||
<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 { IParticipant } from "../../types/participant.model";
|
||||
import { IEvent } from "../../types/event.model";
|
||||
|
@ -191,7 +168,7 @@ import { CONFIG } from "../../graphql/config";
|
|||
import { IConfig } from "../../types/config.model";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
currentUser: {
|
||||
query: CURRENT_USER_CLIENT,
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
<script lang="ts">
|
||||
import { IEvent } from "@/types/event.model";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
EventCard,
|
||||
},
|
||||
|
|
|
@ -123,14 +123,14 @@
|
|||
</template>
|
||||
|
||||
<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 { IEvent } from "../../types/event.model";
|
||||
import DiasporaLogo from "../Share/DiasporaLogo.vue";
|
||||
import MastodonLogo from "../Share/MastodonLogo.vue";
|
||||
import TelegramLogo from "../Share/TelegramLogo.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DiasporaLogo,
|
||||
MastodonLogo,
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
</o-field>
|
||||
</template>
|
||||
<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 { ITag } from "../../types/tag.model";
|
||||
import { FILTER_TAGS } from "@/graphql/tags";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
tags: {
|
||||
query: FILTER_TAGS,
|
||||
|
|
|
@ -81,17 +81,16 @@
|
|||
</footer>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
import { Vue, Watch } from "vue-property-decorator";
|
||||
import { saveLocaleData } from "@/utils/auth";
|
||||
import { loadLanguageAsync } from "@/utils/i18n";
|
||||
import { i18n, loadLanguageAsync } from "@/utils/i18n";
|
||||
import RouteName from "../router/name";
|
||||
import langs from "../i18n/langs.json";
|
||||
|
||||
@Component
|
||||
export default class Footer extends Vue {
|
||||
RouteName = RouteName;
|
||||
|
||||
locale: string | null = this.$i18n.locale;
|
||||
locale: string | null = i18n.global.locale;
|
||||
|
||||
langs: Record<string, string> = langs;
|
||||
|
||||
|
@ -123,7 +122,7 @@ export default class Footer extends Vue {
|
|||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "~bulma/sass/utilities/mixins.sass";
|
||||
@import "../node_modules/bulma/sass/utilities/mixins.sass";
|
||||
footer.footer {
|
||||
color: $secondary;
|
||||
display: flex;
|
||||
|
|
|
@ -56,13 +56,13 @@
|
|||
</template>
|
||||
|
||||
<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 LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
|
||||
import RouteName from "../../router/name";
|
||||
import InlineAddress from "@/components/Address/InlineAddress.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
LazyImageWrapper,
|
||||
InlineAddress,
|
||||
|
|
|
@ -50,7 +50,9 @@
|
|||
</div>
|
||||
<div>
|
||||
<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-icon icon="exit-to-app" />
|
||||
|
@ -63,13 +65,12 @@
|
|||
</template>
|
||||
|
||||
<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 { IMember } from "@/types/actor/member.model";
|
||||
import { MemberRole } from "@/types/enums";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component
|
||||
export default class GroupMemberCard extends Vue {
|
||||
@Prop({ required: true }) member!: IMember;
|
||||
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||
import { Route } from "vue-router";
|
||||
import { Vue, Prop } from "vue-property-decorator";
|
||||
import { RouteLocationNormalizedLoaded } from "vue-router";
|
||||
|
||||
@Component
|
||||
export default class GroupSection extends Vue {
|
||||
@Prop({ required: true, type: String }) title!: string;
|
||||
|
||||
|
@ -29,7 +28,7 @@ export default class GroupSection extends Vue {
|
|||
@Prop({ required: false, type: Boolean, default: true })
|
||||
privateSection!: boolean;
|
||||
|
||||
@Prop({ required: true, type: Object }) route!: Route;
|
||||
@Prop({ required: true, type: Object }) route!: RouteLocationNormalizedLoaded;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -70,12 +70,11 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Prop, Vue } from "vue-property-decorator";
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import { IMember } from "@/types/actor/member.model";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component
|
||||
export default class InvitationCard extends Vue {
|
||||
@Prop({ required: true }) member!: IMember;
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
</template>
|
||||
<script lang="ts">
|
||||
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 { PERSON_STATUS_GROUP } from "@/graphql/actor";
|
||||
import { IMember } from "@/types/actor/member.model";
|
||||
import { IGroup, IPerson, usernameWithDomain } from "@/types/actor";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
InvitationCard,
|
||||
},
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
/>
|
||||
</template>
|
||||
<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 { FETCH_GROUP } from "@/graphql/group";
|
||||
import { IGroup } from "@/types/actor";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: { RedirectWithAccount },
|
||||
apollo: {
|
||||
group: {
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<script lang="ts">
|
||||
import { IGroup } from "@/types/actor";
|
||||
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";
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
GroupCard,
|
||||
},
|
||||
|
|
|
@ -113,14 +113,14 @@
|
|||
</template>
|
||||
|
||||
<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 DiasporaLogo from "../Share/DiasporaLogo.vue";
|
||||
import MastodonLogo from "../Share/MastodonLogo.vue";
|
||||
import TelegramLogo from "../Share/MastodonLogo.vue";
|
||||
import { displayName, IGroup } from "@/types/actor";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DiasporaLogo,
|
||||
MastodonLogo,
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
|
||||
<script lang="ts">
|
||||
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 {
|
||||
@Prop({ type: String, required: true }) hash!: string;
|
||||
@Prop({ type: Number, default: 1 }) aspectRatio!: string;
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
</template>
|
||||
|
||||
<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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
BlurhashImg,
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<script lang="ts">
|
||||
import { IMedia } from "@/types/media.model";
|
||||
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";
|
||||
|
||||
const DEFAULT_CARD_URL = "/img/mobilizon_default_card.png";
|
||||
|
@ -27,7 +27,7 @@ const DEFAULT_PICTURE = {
|
|||
},
|
||||
};
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
LazyImage,
|
||||
},
|
||||
|
|
|
@ -28,13 +28,19 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
@Component
|
||||
export default class Logo extends Vue {
|
||||
@Prop({ type: Boolean, required: false, default: false }) invert!: boolean;
|
||||
}
|
||||
export default defineComponent({
|
||||
props: {
|
||||
invert: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
svg {
|
||||
fill: $background-color;
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
:zoomInTitle="$t('Zoom in')"
|
||||
:zoomOutTitle="$t('Zoom out')"
|
||||
></l-control-zoom>
|
||||
<v-locatecontrol
|
||||
<!-- <v-locatecontrol
|
||||
v-if="canDoGeoLocation"
|
||||
:options="{ icon: 'mdi mdi-map-marker' }"
|
||||
/>
|
||||
/> -->
|
||||
<l-marker
|
||||
:lat-lng="[lat, lon]"
|
||||
@add="openPopup"
|
||||
|
@ -42,7 +42,7 @@
|
|||
<script lang="ts">
|
||||
import { Icon, LatLng, LeafletMouseEvent, LeafletEvent } from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Options, Prop, Vue } from "vue-property-decorator";
|
||||
import {
|
||||
LMap,
|
||||
LTileLayer,
|
||||
|
@ -50,12 +50,12 @@ import {
|
|||
LPopup,
|
||||
LIcon,
|
||||
LControlZoom,
|
||||
} from "vue2-leaflet";
|
||||
import Vue2LeafletLocateControl from "@/components/Map/Vue2LeafletLocateControl.vue";
|
||||
} from "@vue-leaflet/vue-leaflet";
|
||||
// import Vue2LeafletLocateControl from "@/components/Map/Vue2LeafletLocateControl.vue";
|
||||
import { CONFIG } from "../graphql/config";
|
||||
import { IConfig } from "../types/config.model";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
LTileLayer,
|
||||
LMap,
|
||||
|
@ -63,7 +63,7 @@ import { IConfig } from "../types/config.model";
|
|||
LPopup,
|
||||
LIcon,
|
||||
LControlZoom,
|
||||
"v-locatecontrol": Vue2LeafletLocateControl,
|
||||
// "v-locatecontrol": Vue2LeafletLocateControl,
|
||||
},
|
||||
apollo: {
|
||||
config: CONFIG,
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
*/
|
||||
|
||||
import { DomEvent } from "leaflet";
|
||||
import { findRealParent, propsBinder } from "vue2-leaflet";
|
||||
import { findRealParent, propsBinder } from "@vue-leaflet/vue-leaflet";
|
||||
import Locatecontrol from "leaflet.locatecontrol";
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Options, Prop, Vue } from "vue-property-decorator";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
beforeDestroy() {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
|
|
|
@ -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>
|
|
@ -1,185 +1,426 @@
|
|||
<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>
|
||||
<nav class="bg-yellow-100 z-50">
|
||||
<div class="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
|
||||
<div class="relative flex items-center justify-between h-16">
|
||||
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
|
||||
<!-- Mobile menu button-->
|
||||
<button
|
||||
type="button"
|
||||
class="
|
||||
inline-flex
|
||||
items-center
|
||||
justify-center
|
||||
p-2
|
||||
rounded-md
|
||||
text-gray-400
|
||||
hover:text-white hover:bg-yellow-400
|
||||
focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white
|
||||
"
|
||||
aria-controls="mobile-menu"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="sr-only">{{ $t("Open main menu") }}</span>
|
||||
<!--
|
||||
Icon when menu is closed.
|
||||
|
||||
<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
|
||||
Heroicon name: outline/menu
|
||||
|
||||
Menu open: "hidden", Menu closed: "block"
|
||||
-->
|
||||
<svg
|
||||
class="block 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="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
<!--
|
||||
Icon when menu is open.
|
||||
|
||||
Heroicon name: outline/x
|
||||
|
||||
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>
|
||||
</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>
|
||||
<div
|
||||
class="
|
||||
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>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -193,15 +434,21 @@ import {
|
|||
IDENTITIES,
|
||||
UPDATE_DEFAULT_ACTOR,
|
||||
} from "../graphql/actor";
|
||||
import { IPerson, Person } from "../types/actor";
|
||||
import { displayName, 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 { useQuery, useResult } from "@vue/apollo-composable";
|
||||
import {
|
||||
useApolloClient,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useResult,
|
||||
} from "@vue/apollo-composable";
|
||||
import { ref } from "vue";
|
||||
import { ICurrentUserRole } from "@/types/enums";
|
||||
|
||||
export default defineComponent({
|
||||
name: "NavBar",
|
||||
|
@ -214,6 +461,8 @@ export default defineComponent({
|
|||
const currentActor =
|
||||
useResult<{ currentUser: IPerson }>(resultCurrentActor);
|
||||
|
||||
const { mutate: updateDefaultActor } = useMutation(UPDATE_DEFAULT_ACTOR);
|
||||
|
||||
const { result: configResult } = useQuery(CONFIG);
|
||||
const config = useResult<{ config: IConfig }>(configResult);
|
||||
|
||||
|
@ -229,7 +478,9 @@ export default defineComponent({
|
|||
|
||||
const mobileNavbarActive = false;
|
||||
|
||||
const userDropDown = ref(null) as any;
|
||||
const userDropDownOpened = ref(false);
|
||||
|
||||
const { resolveClient } = useApolloClient();
|
||||
|
||||
return {
|
||||
currentUser,
|
||||
|
@ -238,7 +489,12 @@ export default defineComponent({
|
|||
loggedUser,
|
||||
identities,
|
||||
mobileNavbarActive,
|
||||
userDropDown,
|
||||
userDropDownOpened,
|
||||
updateDefaultActor,
|
||||
RouteName,
|
||||
displayName,
|
||||
ICurrentUserRole,
|
||||
resolveClient,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
|
@ -247,10 +503,7 @@ export default defineComponent({
|
|||
},
|
||||
methods: {
|
||||
toggleMenu(): void {
|
||||
console.debug("called toggleMenu");
|
||||
if (this.userDropDown) {
|
||||
this.userDropDown.showMenu();
|
||||
}
|
||||
this.userDropDownOpened = !this.userDropDownOpened;
|
||||
},
|
||||
async handleErrors(errors: GraphQLError[]): Promise<void> {
|
||||
if (
|
||||
|
@ -262,52 +515,41 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
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,
|
||||
});
|
||||
await logout(this.resolveClient());
|
||||
// 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.$apollo.mutate({
|
||||
mutation: UPDATE_DEFAULT_ACTOR,
|
||||
variables: {
|
||||
preferredUsername: identity.preferredUsername,
|
||||
},
|
||||
await this.updateDefaultActor({
|
||||
preferredUsername: identity.preferredUsername,
|
||||
});
|
||||
return changeIdentity(this.$apollo.provider.defaultClient, identity);
|
||||
return changeIdentity(this.resolveClient(), identity);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
async currentActor(): Promise<void> {
|
||||
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,
|
||||
// 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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -64,14 +64,14 @@
|
|||
</template>
|
||||
|
||||
<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 { EventJoinOptions } from "@/types/enums";
|
||||
import { IParticipant } from "../../types/participant.model";
|
||||
import RouteName from "../../router/name";
|
||||
import { CONFIRM_PARTICIPATION } from "../../graphql/event";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
metaInfo() {
|
||||
return {
|
||||
title: this.$t("Confirm participation") as string,
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
<script lang="ts">
|
||||
import { EventJoinOptions, EventStatus, ParticipantRole } from "@/types/enums";
|
||||
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 { IEvent } from "@/types/event.model";
|
||||
import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
|
||||
|
@ -133,7 +133,7 @@ import {
|
|||
} from "@/services/AnonymousParticipationStorage";
|
||||
import ParticipationButton from "../Event/ParticipationButton.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
currentActor: CURRENT_ACTOR_CLIENT,
|
||||
config: CONFIG,
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
/>
|
||||
</template>
|
||||
<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 { FETCH_EVENT } from "@/graphql/event";
|
||||
import { IEvent } from "@/types/event.model";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: { RedirectWithAccount },
|
||||
apollo: {
|
||||
event: {
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
</section>
|
||||
</template>
|
||||
<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 { FETCH_EVENT_BASIC, JOIN_EVENT } from "@/graphql/event";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
|
@ -136,7 +136,7 @@ import RouteName from "@/router/name";
|
|||
import { IParticipant } from "../../types/participant.model";
|
||||
import { ApolloCache, FetchResult } from "@apollo/client/core";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
event: {
|
||||
query: FETCH_EVENT_BASIC,
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
</section>
|
||||
</template>
|
||||
<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 EventListViewCard from "@/components/Event/EventListViewCard.vue";
|
||||
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 RouteName from "../../router/name";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
VerticalDivider,
|
||||
EventListViewCard,
|
||||
|
|
|
@ -112,9 +112,8 @@ figure.image {
|
|||
|
||||
<script lang="ts">
|
||||
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 {
|
||||
@Model("change", { type: File }) readonly pictureFile!: File;
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
<script lang="ts">
|
||||
import { IPost } from "@/types/post.model";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
PostListItem,
|
||||
},
|
||||
|
|
|
@ -42,13 +42,13 @@
|
|||
</template>
|
||||
<script lang="ts">
|
||||
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 { IPost } from "../../types/post.model";
|
||||
import LazyImageWrapper from "@/components/Image/LazyImageWrapper.vue";
|
||||
import { displayName } from "@/types/actor";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
LazyImageWrapper,
|
||||
},
|
||||
|
@ -75,7 +75,7 @@ export default class PostListItem extends Vue {
|
|||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/_mixins" as *;
|
||||
@import "~bulma/sass/utilities/mixins.sass";
|
||||
@import "../node_modules/bulma/sass/utilities/mixins.sass";
|
||||
|
||||
.post-minimalist-card-wrapper {
|
||||
display: grid;
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
</template>
|
||||
|
||||
<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 { IPost } from "../../types/post.model";
|
||||
import DiasporaLogo from "../Share/DiasporaLogo.vue";
|
||||
|
@ -122,7 +122,7 @@ import TelegramLogo from "../Share/TelegramLogo.vue";
|
|||
import { PropType } from "vue";
|
||||
import RouteName from "@/router/name";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: {
|
||||
DiasporaLogo,
|
||||
MastodonLogo,
|
||||
|
|
|
@ -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>
|
||||
<div class="card" v-if="report">
|
||||
<div class="card-content">
|
||||
|
@ -42,11 +37,10 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 { ActorType } from "@/types/enums";
|
||||
|
||||
@Component
|
||||
export default class ReportCard extends Vue {
|
||||
@Prop({ required: true }) report!: IReport;
|
||||
|
||||
|
|
|
@ -90,10 +90,10 @@
|
|||
</template>
|
||||
|
||||
<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";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
mounted() {
|
||||
this.$data.isActive = true;
|
||||
},
|
||||
|
|
|
@ -37,21 +37,21 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Mixins, Prop } from "vue-property-decorator";
|
||||
import { Route } from "vue-router";
|
||||
import { Options, mixins, Prop } from "vue-property-decorator";
|
||||
import Draggable, { ChangeEvent } from "vuedraggable";
|
||||
import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
// import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { IResource } from "../../types/resource";
|
||||
import RouteName from "../../router/name";
|
||||
import ResourceMixin from "../../mixins/resource";
|
||||
import { IGroup, usernameWithDomain } from "../../types/actor";
|
||||
import ResourceDropdown from "./ResourceDropdown.vue";
|
||||
import { UPDATE_RESOURCE } from "../../graphql/resources";
|
||||
import { NavigationFailure } from "vue-router";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
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 }) group!: IGroup;
|
||||
|
@ -72,7 +72,9 @@ export default class FolderItem extends Mixins(ResourceMixin) {
|
|||
|
||||
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) {
|
||||
const movedResource = evt.added.element as IResource;
|
||||
const updatedResource = await this.moveResource(movedResource);
|
||||
|
@ -111,11 +113,11 @@ export default class FolderItem extends Mixins(ResourceMixin) {
|
|||
}
|
||||
return data.updateResource;
|
||||
} catch (e: any) {
|
||||
Snackbar.open({
|
||||
message: e.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
// Snackbar.open({
|
||||
// message: e.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
</o-dropdown>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { Vue } from "vue-property-decorator";
|
||||
|
||||
@Component
|
||||
export default class ResourceDropdown extends Vue {}
|
||||
</script>
|
||||
|
|
|
@ -53,11 +53,11 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 ResourceDropdown from "@/components/Resource/ResourceDropdown.vue";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: { ResourceDropdown },
|
||||
})
|
||||
export default class ResourceItem extends Vue {
|
||||
|
|
|
@ -89,11 +89,11 @@
|
|||
</div>
|
||||
</template>
|
||||
<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 { IResource } from "../../types/resource";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
apollo: {
|
||||
resource: {
|
||||
query: GET_RESOURCE,
|
||||
|
|
|
@ -1,42 +1,78 @@
|
|||
<template>
|
||||
<label for="navSearchField">
|
||||
<span class="visually-hidden">{{ defaultPlaceHolder }}</span>
|
||||
<o-input
|
||||
custom-class="searchField"
|
||||
id="navSearchField"
|
||||
icon="magnify"
|
||||
<div class="flex relative mx-auto w-full max-w-md">
|
||||
<label for="navSearchField" class="sr-only">{{ defaultPlaceHolder }}</label>
|
||||
<input
|
||||
class="
|
||||
border-2 border-primary
|
||||
bg-red
|
||||
transition
|
||||
h-12
|
||||
px-5
|
||||
pr-16
|
||||
rounded-md
|
||||
focus:outline-none
|
||||
w-full
|
||||
text-black text-lg
|
||||
"
|
||||
type="search"
|
||||
rounded
|
||||
name="search"
|
||||
id="navSearchField"
|
||||
dir="auto"
|
||||
:placeholder="defaultPlaceHolder"
|
||||
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>
|
||||
<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";
|
||||
|
||||
@Component
|
||||
export default class SearchField extends Vue {
|
||||
@Prop({ type: String, required: false }) placeholder!: string;
|
||||
export default defineComponent({
|
||||
props: {
|
||||
placeholder: {
|
||||
required: false,
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const search = "";
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
|
||||
search = "";
|
||||
|
||||
async enter(): Promise<void> {
|
||||
this.$emit("navbar-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);
|
||||
}
|
||||
}
|
||||
const defaultPlaceHolder = props.placeholder || t("Search");
|
||||
return { search, defaultPlaceHolder };
|
||||
},
|
||||
methods: {
|
||||
async enter(): Promise<void> {
|
||||
this.$emit("navbar-search");
|
||||
await this.$router.push({
|
||||
name: RouteName.SEARCH,
|
||||
query: { term: this.search },
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
@ -40,12 +40,10 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component } from "vue-property-decorator";
|
||||
import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { mixins } from "vue-class-component";
|
||||
// import { SnackbarProgrammatic as Snackbar } from "buefy";
|
||||
import { mixins } from "vue-property-decorator";
|
||||
import Onboarding from "../../mixins/onboarding";
|
||||
|
||||
@Component
|
||||
export default class NotificationsOnboarding extends mixins(Onboarding) {
|
||||
notificationOnDay = true;
|
||||
|
||||
|
@ -61,11 +59,11 @@ export default class NotificationsOnboarding extends mixins(Onboarding) {
|
|||
try {
|
||||
this.doUpdateSetting(variables);
|
||||
} catch (e: any) {
|
||||
Snackbar.open({
|
||||
message: e.message,
|
||||
type: "is-danger",
|
||||
position: "is-bottom",
|
||||
});
|
||||
// Snackbar.open({
|
||||
// message: e.message,
|
||||
// type: "is-danger",
|
||||
// position: "is-bottom",
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
</li>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { Route } from "vue-router";
|
||||
import { Prop, Vue } from "vue-property-decorator";
|
||||
import { RouteLocationNormalizedLoaded } from "vue-router";
|
||||
|
||||
@Component
|
||||
export default class SettingMenuItem extends Vue {
|
||||
@Prop({ required: false, type: String }) title!: string;
|
||||
|
||||
@Prop({ required: true, type: Object }) to!: Route;
|
||||
@Prop({ required: true, type: Object }) to!: RouteLocationNormalizedLoaded;
|
||||
|
||||
get isActive(): boolean {
|
||||
if (!this.to) return false;
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
</li>
|
||||
</template>
|
||||
<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 { Route } from "vue-router";
|
||||
|
||||
@Component({
|
||||
@Options({
|
||||
components: { SettingMenuItem },
|
||||
})
|
||||
export default class SettingMenuSection extends Vue {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue