diff --git a/js/package.json b/js/package.json index 3d418dbde..f10b3f45c 100644 --- a/js/package.json +++ b/js/package.json @@ -36,16 +36,16 @@ "ngeohash": "^0.6.3", "phoenix": "^1.4.11", "register-service-worker": "^1.7.1", - "tippy.js": "4.3.5", + "tippy.js": "^6.2.3", "tiptap": "^1.26.0", - "tiptap-extensions": "^1.28.0", + "tiptap-extensions": "^1.29.1", "v-tooltip": "2.0.2", "vue": "^2.6.11", "vue-apollo": "^3.0.3", "vue-class-component": "^7.2.3", "vue-i18n": "^8.14.0", "vue-meta": "^2.3.1", - "vue-property-decorator": "^8.4.1", + "vue-property-decorator": "^9.0.0", "vue-router": "^3.1.6", "vue-scrollto": "^2.17.1", "vue2-leaflet": "^2.0.3", @@ -90,7 +90,7 @@ "prettier-eslint": "^10.1.1", "sass-loader": "^8.0.2", "typescript": "~3.9.3", - "vue-cli-plugin-styleguidist": "~4.24.0", + "vue-cli-plugin-styleguidist": "^4.25.0", "vue-cli-plugin-svg": "~0.1.3", "vue-i18n-extract": "^1.0.2", "vue-template-compiler": "^2.6.11", diff --git a/js/src/components/Editor.vue b/js/src/components/Editor.vue index beae1205a..43800c8fa 100644 --- a/js/src/components/Editor.vue +++ b/js/src/components/Editor.vue @@ -156,14 +156,21 @@
- {{ actor.name }} +
+
+ +
+
+
+ {{ actor.name }} +
-
{{ $t("No actors found") }}
+
{{ $t("No profiles found") }}
@@ -189,7 +196,7 @@ import { Placeholder, Mention, } from "tiptap-extensions"; -import tippy, { Instance } from "tippy.js"; +import tippy, { Instance, sticky } from "tippy.js"; import { SEARCH_PERSONS } from "../graphql/search"; import { Actor, IActor, IPerson } from "../types/actor"; import Image from "./Editor/Image"; @@ -226,7 +233,7 @@ export default class EditorComponent extends Vue { navigatedActorIndex = 0; - popup!: Instance | null; + popup!: Instance[] | null; get isDescriptionMode() { return this.mode === "description"; @@ -319,18 +326,15 @@ export default class EditorComponent extends Vue { * is called on every keyDown event while a suggestion is active */ onKeyDown: ({ event }: { event: KeyboardEvent }) => { - // pressing up arrow - if (event.keyCode === 38) { + if (event.key === "ArrowUp") { this.upHandler(); return true; } - // pressing down arrow - if (event.keyCode === 40) { + if (event.key === "ArrowDown") { this.downHandler(); return true; } - // pressing enter - if (event.keyCode === 13) { + if (event.key === "Enter") { this.enterHandler(); return true; } @@ -440,6 +444,7 @@ export default class EditorComponent extends Vue { this.editor.focus(); } + /** We use this to programatically insert an actor mention when creating a reply to comment */ replyToComment(comment: IComment) { const actorModel = new Actor(comment.actor); if (!this.editor) return; @@ -455,40 +460,31 @@ export default class EditorComponent extends Vue { * tiptap provides a virtualNode object for using popper.js (or tippy.js) for popups * @param node */ - renderPopup(node: any) { + renderPopup(node: Element) { if (this.popup) { return; } - this.popup = tippy(node, { + this.popup = tippy("#mobilizon", { + // @ts-ignore + getReferenceClientRect: node.getBoundingClientRect, + appendTo: () => document.body, content: this.$refs.suggestions as HTMLElement, trigger: "mouseenter", interactive: true, + sticky: true, // make sure position of tippy is updated when content changes + plugins: [sticky], + showOnCreate: true, theme: "dark", placement: "top-start", inertia: true, duration: [400, 200], - showOnInit: true, - arrow: true, - arrowType: "round", - }) as Instance; - // we have to update tippy whenever the DOM is updated - if (MutationObserver) { - this.observer = new MutationObserver(() => { - if (this.popup != null && this.popup.popperInstance) { - this.popup.popperInstance.scheduleUpdate(); - } - }); - this.observer.observe(this.$refs.suggestions as HTMLElement, { - childList: true, - subtree: true, - characterData: true, - }); - } + }) as Instance[]; } destroyPopup() { if (this.popup) { - this.popup.destroy(); + // @ts-ignore + this.popup[0].destroy(); this.popup = null; } if (this.observer) { @@ -517,6 +513,7 @@ export default class EditorComponent extends Vue { beforeDestroy() { if (!this.editor) return; + this.destroyPopup(); this.editor.destroy(); } } @@ -733,32 +730,19 @@ $color-white: #eee; opacity: 0.5; } } + + .media + .media { + margin-top: 0; + padding-top: 0; + } } -.tippy-tooltip.dark-theme { +.tippy-box[data-theme~="dark"] { background-color: $color-black; padding: 0; font-size: 1rem; text-align: inherit; color: $color-white; border-radius: 5px; - .tippy-backdrop { - display: none; - } - .tippy-roundarrow { - fill: $color-black; - } - .tippy-popper[x-placement^="top"] & .tippy-arrow { - border-top-color: $color-black; - } - .tippy-popper[x-placement^="bottom"] & .tippy-arrow { - border-bottom-color: $color-black; - } - .tippy-popper[x-placement^="left"] & .tippy-arrow { - border-left-color: $color-black; - } - .tippy-popper[x-placement^="right"] & .tippy-arrow { - border-right-color: $color-black; - } } .visually-hidden { diff --git a/js/src/components/Settings/SettingsMenu.vue b/js/src/components/Settings/SettingsMenu.vue index 8084e8238..419ce3f3b 100644 --- a/js/src/components/Settings/SettingsMenu.vue +++ b/js/src/components/Settings/SettingsMenu.vue @@ -1,7 +1,13 @@ + + diff --git a/js/src/views/About/AboutMobilizon.vue b/js/src/views/About/AboutMobilizon.vue new file mode 100644 index 000000000..33bfbb182 --- /dev/null +++ b/js/src/views/About/AboutMobilizon.vue @@ -0,0 +1,236 @@ + + + + + diff --git a/js/src/views/About/Glossary.vue b/js/src/views/About/Glossary.vue new file mode 100644 index 000000000..1c14cbf34 --- /dev/null +++ b/js/src/views/About/Glossary.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/js/src/views/About/Privacy.vue b/js/src/views/About/Privacy.vue new file mode 100644 index 000000000..b6ee7e69f --- /dev/null +++ b/js/src/views/About/Privacy.vue @@ -0,0 +1,66 @@ + + + + diff --git a/js/src/views/Rules.vue b/js/src/views/About/Rules.vue similarity index 89% rename from js/src/views/Rules.vue rename to js/src/views/About/Rules.vue index f8a48f2d8..3750b5acc 100644 --- a/js/src/views/Rules.vue +++ b/js/src/views/About/Rules.vue @@ -11,7 +11,7 @@ import { Component, Vue, Watch } from "vue-property-decorator"; import { RULES } from "@/graphql/config"; import { IConfig } from "@/types/config.model"; import { InstanceTermsType } from "@/types/admin.model"; -import RouteName from "../router/name"; +import RouteName from "../../router/name"; @Component({ apollo: { @@ -32,4 +32,7 @@ export default class Rules extends Vue { main > .container { background: $white; } +.content /deep/ li { + margin-bottom: 1rem; +} diff --git a/js/src/views/Terms.vue b/js/src/views/About/Terms.vue similarity index 85% rename from js/src/views/Terms.vue rename to js/src/views/About/Terms.vue index caa200994..466189a62 100644 --- a/js/src/views/Terms.vue +++ b/js/src/views/About/Terms.vue @@ -1,6 +1,6 @@ @@ -10,7 +10,6 @@ import { Component, Vue, Watch } from "vue-property-decorator"; import { TERMS } from "@/graphql/config"; import { IConfig } from "@/types/config.model"; import { InstanceTermsType } from "@/types/admin.model"; -import RouteName from "../router/name"; @Component({ apollo: { @@ -49,14 +48,10 @@ export default class Terms extends Vue { window.location.replace(this.config.terms.url); } } - - RouteName = RouteName; } diff --git a/js/src/views/Admin/Profiles.vue b/js/src/views/Admin/Profiles.vue index e4a2ee53c..f757e2f51 100644 --- a/js/src/views/Admin/Profiles.vue +++ b/js/src/views/Admin/Profiles.vue @@ -23,7 +23,10 @@ size="is-small" /> - +

@@ -136,3 +139,8 @@ export default class Profiles extends Vue { } } + diff --git a/js/src/views/Admin/Settings.vue b/js/src/views/Admin/Settings.vue index 74a9f1a16..519c031e8 100644 --- a/js/src/views/Admin/Settings.vue +++ b/js/src/views/Admin/Settings.vue @@ -4,9 +4,24 @@ - - - +

+ + + {{ + $t( + "Displayed on homepage and meta tags. Describe what Mobilizon is and what makes this instance special in a single paragraph." + ) + }} + + +
+
+ + + {{ $t("Can be an email or a link, or just plain text.") }} + + +

@@ -15,9 +30,24 @@

{{ $t("Registration is closed.") }}

- +
+ + + {{ + $t( + "A place to explain who you are and the things that set your instance apart. You can use HTML tags." + ) + }} + + +
+
+ + + {{ $t("A place for your code of conduct, rules or guidelines. You can use HTML tags.") }} + - +
@@ -26,7 +56,7 @@ v-model="adminSettings.instanceTermsType" name="instanceTermsType" :native-value="InstanceTermsType.DEFAULT" - >{{ $t("Default Mobilizon.org terms") }}{{ $t("Default Mobilizon terms") }} @@ -65,6 +95,11 @@ >{{ $t("default Mobilizon terms") }} + {{ + $t( + "NOTE! The default terms have not been checked over by a lawyer and thus are unlikely to provide full legal protection for all situations for an instance admin using them. They are also not specific to all countries and jurisdictions. If you are unsure, please check with a lawyer." + ) + }}
{{ $t("Custom") }} -

- {{ - $t( - "Enter your own terms. HTML tags allowed. Mobilizon.org's terms are provided as template." - ) - }} -

+ + + {{ $t("default Mobilizon terms") }} +
@@ -99,7 +141,97 @@ :label="$t('Instance Terms')" v-if="adminSettings.instanceTermsType === InstanceTermsType.CUSTOM" > - + +
+ +
+
+ + {{ $t("Default Mobilizon privacy policy") }} + + + {{ $t("Custom URL") }} + + + {{ $t("Custom text") }} + +
+
+
+ {{ $t("Default") }} + + {{ $t("default Mobilizon privacy policy") }} + +
+
+ {{ $t("URL") }} +

{{ $t("Set an URL to a page with your own privacy policy.") }}

+
+ +
+
+
+ + + + + {{ $t("Save") }} @@ -108,7 +240,7 @@