forked from potsda.mn/mobilizon
Resource fixes
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
9ab95efb08
commit
4c9065ce68
|
@ -45,7 +45,7 @@
|
||||||
</a>
|
</a>
|
||||||
<resource-dropdown
|
<resource-dropdown
|
||||||
class="actions"
|
class="actions"
|
||||||
v-if="!inline || !preview"
|
v-if="!inline && !preview"
|
||||||
@delete="$emit('delete', resource.id)"
|
@delete="$emit('delete', resource.id)"
|
||||||
@move="$emit('move', resource)"
|
@move="$emit('move', resource)"
|
||||||
@rename="$emit('rename', resource)"
|
@rename="$emit('rename', resource)"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="resource">
|
<div v-if="resource">
|
||||||
<article class="panel is-primary">
|
<article class="panel is-primary">
|
||||||
<p class="panel-heading">
|
<p class="panel-heading truncate">
|
||||||
{{
|
{{
|
||||||
$t('Move "{resourceName}"', { resourceName: initialResource.title })
|
$t('Move "{resourceName}"', { resourceName: initialResource.title })
|
||||||
}}
|
}}
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
</a>
|
</a>
|
||||||
<template v-if="resource.children">
|
<template v-if="resource.children">
|
||||||
<a
|
<a
|
||||||
class="panel-block"
|
class="panel-block flex-wrap"
|
||||||
v-for="element in resource.children.elements"
|
v-for="element in resource.children.elements"
|
||||||
:class="{
|
:class="{
|
||||||
clickable:
|
clickable:
|
||||||
|
@ -37,15 +37,17 @@
|
||||||
:key="element.id"
|
:key="element.id"
|
||||||
@click="goDown(element)"
|
@click="goDown(element)"
|
||||||
>
|
>
|
||||||
<span class="panel-icon">
|
<p class="truncate">
|
||||||
<b-icon
|
<span class="panel-icon">
|
||||||
icon="folder"
|
<b-icon
|
||||||
size="is-small"
|
icon="folder"
|
||||||
v-if="element.type === 'folder'"
|
size="is-small"
|
||||||
/>
|
v-if="element.type === 'folder'"
|
||||||
<b-icon icon="link" size="is-small" v-else />
|
/>
|
||||||
</span>
|
<b-icon icon="link" size="is-small" v-else />
|
||||||
{{ element.title }}
|
</span>
|
||||||
|
<span>{{ element.title }}</span>
|
||||||
|
</p>
|
||||||
<span v-if="element.id === initialResource.id">
|
<span v-if="element.id === initialResource.id">
|
||||||
<em v-if="element.type === 'folder'"> {{ $t("(this folder)") }}</em>
|
<em v-if="element.type === 'folder'"> {{ $t("(this folder)") }}</em>
|
||||||
<em v-else> {{ $t("(this link)") }}</em>
|
<em v-else> {{ $t("(this link)") }}</em>
|
||||||
|
@ -89,7 +91,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Prop } from "vue-property-decorator";
|
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
|
||||||
import { GET_RESOURCE } from "../../graphql/resources";
|
import { GET_RESOURCE } from "../../graphql/resources";
|
||||||
import { IResource } from "../../types/resource";
|
import { IResource } from "../../types/resource";
|
||||||
|
|
||||||
|
@ -119,7 +121,7 @@ export default class ResourceSelector extends Vue {
|
||||||
|
|
||||||
@Prop({ required: true }) username!: string;
|
@Prop({ required: true }) username!: string;
|
||||||
|
|
||||||
resource: IResource | undefined = this.initialResource.parent;
|
resource: IResource | undefined = undefined;
|
||||||
|
|
||||||
RESOURCES_PER_PAGE = 10;
|
RESOURCES_PER_PAGE = 10;
|
||||||
|
|
||||||
|
@ -131,6 +133,20 @@ export default class ResourceSelector extends Vue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
resource: this.initialResource?.parent,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Watch("initialResource")
|
||||||
|
updateResourceFromProp() {
|
||||||
|
if (this.initialResource) {
|
||||||
|
this.resource = this.initialResource?.parent;
|
||||||
|
this.$apollo.queries.resource.refetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateResource(): void {
|
updateResource(): void {
|
||||||
this.$emit(
|
this.$emit(
|
||||||
"update-resource",
|
"update-resource",
|
||||||
|
|
|
@ -9,10 +9,7 @@
|
||||||
<b-icon icon="folder" />
|
<b-icon icon="folder" />
|
||||||
{{ $t("New folder") }}
|
{{ $t("New folder") }}
|
||||||
</b-dropdown-item>
|
</b-dropdown-item>
|
||||||
<b-dropdown-item
|
<b-dropdown-item aria-role="listitem" @click="createLinkModal">
|
||||||
aria-role="listitem"
|
|
||||||
@click="createLinkResourceModal = true"
|
|
||||||
>
|
|
||||||
<b-icon icon="link" />
|
<b-icon icon="link" />
|
||||||
{{ $t("New link") }}
|
{{ $t("New link") }}
|
||||||
</b-dropdown-item>
|
</b-dropdown-item>
|
||||||
|
@ -124,7 +121,11 @@
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
<form @submit.prevent="renameResource">
|
<form @submit.prevent="renameResource">
|
||||||
<b-field :label="$t('Title')">
|
<b-field :label="$t('Title')">
|
||||||
<b-input aria-required="true" v-model="updatedResource.title" />
|
<b-input
|
||||||
|
ref="resourceRenameInput"
|
||||||
|
aria-required="true"
|
||||||
|
v-model="updatedResource.title"
|
||||||
|
/>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-button native-type="submit">{{
|
<b-button native-type="submit">{{
|
||||||
|
@ -154,12 +155,17 @@
|
||||||
:active.sync="createResourceModal"
|
:active.sync="createResourceModal"
|
||||||
has-modal-card
|
has-modal-card
|
||||||
:close-button-aria-label="$t('Close')"
|
:close-button-aria-label="$t('Close')"
|
||||||
|
trap-focus
|
||||||
>
|
>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
|
<b-message type="is-danger" v-if="modalError">
|
||||||
|
{{ modalError }}
|
||||||
|
</b-message>
|
||||||
<form @submit.prevent="createResource">
|
<form @submit.prevent="createResource">
|
||||||
<b-field :label="$t('Title')" label-for="new-resource-title">
|
<b-field :label="$t('Title')" label-for="new-resource-title">
|
||||||
<b-input
|
<b-input
|
||||||
|
ref="modalNewResourceInput"
|
||||||
aria-required="true"
|
aria-required="true"
|
||||||
v-model="newResource.title"
|
v-model="newResource.title"
|
||||||
id="new-resource-title"
|
id="new-resource-title"
|
||||||
|
@ -179,6 +185,7 @@
|
||||||
class="link-resource-modal"
|
class="link-resource-modal"
|
||||||
aria-modal
|
aria-modal
|
||||||
:close-button-aria-label="$t('Close')"
|
:close-button-aria-label="$t('Close')"
|
||||||
|
trap-focus
|
||||||
>
|
>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
|
@ -193,6 +200,7 @@
|
||||||
required
|
required
|
||||||
v-model="newResource.resourceUrl"
|
v-model="newResource.resourceUrl"
|
||||||
@blur="previewResource"
|
@blur="previewResource"
|
||||||
|
ref="modalNewResourceLinkInput"
|
||||||
/>
|
/>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
|
@ -355,6 +363,12 @@ export default class Resources extends Mixins(ResourceMixin) {
|
||||||
put: true,
|
put: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$refs!: {
|
||||||
|
resourceRenameInput: any;
|
||||||
|
modalNewResourceInput: HTMLElement;
|
||||||
|
modalNewResourceLinkInput: HTMLElement;
|
||||||
|
};
|
||||||
|
|
||||||
mapServiceTypeToIcon = mapServiceTypeToIcon;
|
mapServiceTypeToIcon = mapServiceTypeToIcon;
|
||||||
|
|
||||||
get page(): number {
|
get page(): number {
|
||||||
|
@ -458,15 +472,25 @@ export default class Resources extends Mixins(ResourceMixin) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createFolderModal(): void {
|
async createLinkModal(): Promise<void> {
|
||||||
this.newResource.type = "folder";
|
this.createLinkResourceModal = true;
|
||||||
this.createResourceModal = true;
|
await this.$nextTick();
|
||||||
|
this.$refs.modalNewResourceLinkInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
createResourceFromProvider(provider: IProvider): void {
|
async createFolderModal(): Promise<void> {
|
||||||
|
this.newResource.type = "folder";
|
||||||
|
this.createResourceModal = true;
|
||||||
|
await this.$nextTick();
|
||||||
|
this.$refs.modalNewResourceInput.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createResourceFromProvider(provider: IProvider): Promise<void> {
|
||||||
this.newResource.resourceUrl = Resources.generateFullResourceUrl(provider);
|
this.newResource.resourceUrl = Resources.generateFullResourceUrl(provider);
|
||||||
this.newResource.type = provider.software;
|
this.newResource.type = provider.software;
|
||||||
this.createResourceModal = true;
|
this.createResourceModal = true;
|
||||||
|
await this.$nextTick();
|
||||||
|
this.$refs.modalNewResourceInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
static generateFullResourceUrl(provider: IProvider): string {
|
static generateFullResourceUrl(provider: IProvider): string {
|
||||||
|
@ -549,10 +573,12 @@ export default class Resources extends Mixins(ResourceMixin) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRename(resource: IResource): void {
|
async handleRename(resource: IResource): Promise<void> {
|
||||||
console.log("handleRename");
|
|
||||||
this.renameModal = true;
|
this.renameModal = true;
|
||||||
this.updatedResource = { ...resource };
|
this.updatedResource = { ...resource };
|
||||||
|
await this.$nextTick();
|
||||||
|
this.$refs.resourceRenameInput.focus();
|
||||||
|
this.$refs.resourceRenameInput.$el.querySelector("input").select();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMove(resource: IResource): void {
|
handleMove(resource: IResource): void {
|
||||||
|
|
|
@ -122,6 +122,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Resource do
|
||||||
{:ok, _, %Resource{} = resource} ->
|
{:ok, _, %Resource{} = resource} ->
|
||||||
{:ok, resource}
|
{:ok, resource}
|
||||||
|
|
||||||
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
|
{:error, changeset}
|
||||||
|
|
||||||
{:error, _err} ->
|
{:error, _err} ->
|
||||||
{:error, dgettext("errors", "Error while creating resource")}
|
{:error, dgettext("errors", "Error while creating resource")}
|
||||||
end
|
end
|
||||||
|
|
|
@ -63,6 +63,10 @@ defmodule Mobilizon.Resources.Resource do
|
||||||
|> maybe_add_published_at()
|
|> maybe_add_published_at()
|
||||||
|> validate_resource_or_folder()
|
|> validate_resource_or_folder()
|
||||||
|> validate_required(@required_attrs)
|
|> validate_required(@required_attrs)
|
||||||
|
|> validate_length(:title, max: 200)
|
||||||
|
|> validate_length(:summary, max: 400)
|
||||||
|
|> validate_length(:resource_url, max: 400)
|
||||||
|
|> validate_length(:path, max: 500)
|
||||||
|> unique_constraint(:url, name: :resource_url_index)
|
|> unique_constraint(:url, name: :resource_url_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,11 @@ defmodule Mobilizon.Resources do
|
||||||
{:ok, resource}
|
{:ok, resource}
|
||||||
|
|
||||||
{:error, operation, reason, _changes} ->
|
{:error, operation, reason, _changes} ->
|
||||||
{:error, "Error while inserting resource when #{operation} because of #{inspect(reason)}"}
|
Logger.error(
|
||||||
|
"Error while inserting resource when #{operation} because of #{inspect(reason)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
{:error, reason}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue