Complete folder share

old-stable24^2
Varun Patil 2022-10-28 22:24:19 -07:00
parent fd4105e913
commit b84b4e6de1
6 changed files with 254 additions and 22 deletions

View File

@ -490,10 +490,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
// Folder
if (this.$route.name === "folders") {
let path: any = this.$route.params.path || "/";
path = typeof path === "string" ? path : path.join("/");
path = this.config_foldersPath + "/" + path;
query.set("folder", path);
query.set("folder", utils.getFolderRoutePath(this.config_foldersPath));
}
// Archive

View File

@ -0,0 +1,114 @@
<template>
<Modal
@close="close"
size="normal"
v-if="show"
:sidebar="!isRoot ? this.folderPath : null"
>
<template #title>
{{ t("memories", "Share Folder") }}
</template>
<div v-if="isRoot">
{{ t("memories", "You cannot share the root folder") }}
</div>
<div v-else>
{{ t("memories", "Use the sidebar to share this folder.") }} <br />
{{
t(
"memories",
"If you create a public link share, click on refresh and a corresponding link to Memories will be shown below."
)
}}
</div>
<div class="links">
<a
v-for="link of links"
:key="link.url"
:href="link.url"
target="_blank"
rel="noopener noreferrer"
>
{{ link.url }}
</a>
</div>
<template #buttons>
<NcButton class="primary" @click="refreshUrls">
{{ t("memories", "Refresh") }}
</NcButton>
</template>
</Modal>
</template>
<script lang="ts">
import { Component, Emit, Mixins } from "vue-property-decorator";
import axios from "@nextcloud/axios";
import { generateOcsUrl, generateUrl } from "@nextcloud/router";
import { NcButton } from "@nextcloud/vue";
import * as utils from "../../services/Utils";
import Modal from "./Modal.vue";
import GlobalMixin from "../../mixins/GlobalMixin";
import UserConfig from "../../mixins/UserConfig";
import { Type } from "@nextcloud/sharing";
@Component({
components: {
Modal,
NcButton,
},
})
export default class FolderShareModal extends Mixins(GlobalMixin, UserConfig) {
private show = false;
private folderPath = "";
private links: { url: string }[] = [];
get isRoot() {
return this.folderPath === "/" || this.folderPath === "";
}
@Emit("close")
public close() {
this.show = false;
}
public open() {
this.folderPath = utils.getFolderRoutePath(this.config_foldersPath);
this.show = true;
globalThis.OCA.Files.Sidebar.setActiveTab("sharing");
this.refreshUrls();
}
private async refreshUrls() {
const query = `format=json&path=${encodeURIComponent(
this.folderPath
)}&reshares=true`;
const url = generateOcsUrl(`/apps/files_sharing/api/v1/shares?${query}`);
const response = await axios.get(url);
const data = response.data?.ocs?.data;
if (data) {
this.links = data
.filter((s) => s.share_type === Type.SHARE_TYPE_LINK && s.token)
.map((share: any) => ({
url:
window.location.origin +
generateUrl(`/apps/memories/s/${share.token}`),
}));
}
}
}
</script>
<style lang="scss" scoped>
.links {
margin-top: 1em;
a {
display: block;
margin-bottom: 0.2em;
color: var(--color-primary-element);
}
}
</style>

View File

@ -1,5 +1,11 @@
<template>
<NcModal :size="size" @close="close" :outTransition="true">
<NcModal
:size="size"
@close="close"
:outTransition="true"
:style="{ width: isSidebarShown ? `calc(100% - ${sidebarWidth}px)` : null }"
:additionalTrapElements="trapElements"
>
<div class="container">
<div class="head">
<span> <slot name="title"></slot> </span>
@ -17,6 +23,7 @@
<script lang="ts">
import { Component, Emit, Prop, Vue } from "vue-property-decorator";
import { NcModal } from "@nextcloud/vue";
import { subscribe, unsubscribe } from "@nextcloud/event-bus";
@Component({
components: {
@ -25,9 +32,66 @@ import { NcModal } from "@nextcloud/vue";
})
export default class Modal extends Vue {
@Prop({ default: "small" }) private size?: string;
@Prop({ default: null }) private sidebar?: string;
private isSidebarShown = false;
private sidebarWidth = 400;
private trapElements: any = [];
@Emit("close")
public close() {}
beforeMount() {
if (this.sidebar) {
subscribe("files:sidebar:opened", this.handleAppSidebarOpen);
subscribe("files:sidebar:closed", this.handleAppSidebarClose);
window.addEventListener("DOMNodeInserted", this.handlePopover);
globalThis.OCA?.Files?.Sidebar?.setFullScreenMode?.(true);
}
}
beforeDestroy() {
if (this.sidebar) {
unsubscribe("files:sidebar:opened", this.handleAppSidebarOpen);
unsubscribe("files:sidebar:closed", this.handleAppSidebarClose);
window.removeEventListener("DOMNodeInserted", this.handlePopover);
globalThis.OCA?.Files?.Sidebar?.setFullScreenMode?.(false);
globalThis.OCA?.Files?.Sidebar?.close();
}
}
mounted() {
if (this.sidebar) {
globalThis.OCA.Files.Sidebar.open(this.sidebar);
}
}
/**
* Watch out for Popover inject in document root
* That way we can adjust the focusTrap
*/
handlePopover(event) {
if (
event.target?.classList &&
event.target.classList.contains("v-popper__popper")
) {
this.trapElements.push(event.target);
}
}
handleAppSidebarOpen() {
this.isSidebarShown = true;
const sidebar: HTMLElement = document.querySelector("aside.app-sidebar");
if (sidebar) {
this.sidebarWidth = sidebar.offsetWidth;
this.trapElements = [sidebar];
}
}
handleAppSidebarClose() {
this.isSidebarShown = false;
this.trapElements = [];
}
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<div class="album-top-matter">
<div class="top-matter">
<NcActions v-if="!isAlbumList">
<NcActionButton :aria-label="t('memories', 'Back')" @click="back()">
{{ t("memories", "Back") }}
@ -124,7 +124,7 @@ export default class AlbumTopMatter extends Mixins(GlobalMixin, UserConfig) {
</script>
<style lang="scss" scoped>
.album-top-matter {
.top-matter {
display: flex;
vertical-align: middle;

View File

@ -1,31 +1,61 @@
<template>
<NcBreadcrumbs v-if="topMatter">
<NcBreadcrumb title="Home" :to="{ name: 'folders' }">
<template #icon>
<HomeIcon :size="20" />
</template>
</NcBreadcrumb>
<NcBreadcrumb
v-for="folder in topMatter.list"
:key="folder.path"
:title="folder.text"
:to="{ name: 'folders', params: { path: folder.path } }"
/>
</NcBreadcrumbs>
<div class="top-matter">
<NcBreadcrumbs v-if="topMatter">
<NcBreadcrumb title="Home" :to="{ name: 'folders' }">
<template #icon>
<HomeIcon :size="20" />
</template>
</NcBreadcrumb>
<NcBreadcrumb
v-for="folder in topMatter.list"
:key="folder.path"
:title="folder.text"
:to="{ name: 'folders', params: { path: folder.path } }"
/>
</NcBreadcrumbs>
<div class="right-actions">
<NcActions :inline="1">
<NcActionButton
:aria-label="t('memories', 'Share folder')"
@click="$refs.shareModal.open(false)"
close-after-click
>
{{ t("memories", "Share folder") }}
<template #icon> <ShareIcon :size="20" /> </template>
</NcActionButton>
</NcActions>
</div>
<FolderShareModal ref="shareModal" />
</div>
</template>
<script lang="ts">
import { Component, Mixins, Watch } from "vue-property-decorator";
import { TopMatterFolder, TopMatterType } from "../../types";
import { NcBreadcrumbs, NcBreadcrumb } from "@nextcloud/vue";
import {
NcBreadcrumbs,
NcBreadcrumb,
NcActions,
NcActionButton,
} from "@nextcloud/vue";
import GlobalMixin from "../../mixins/GlobalMixin";
import FolderShareModal from "../modal/FolderShareModal.vue";
import HomeIcon from "vue-material-design-icons/Home.vue";
import ShareIcon from "vue-material-design-icons/ShareVariant.vue";
@Component({
components: {
NcBreadcrumbs,
NcBreadcrumb,
NcActions,
NcActionButton,
FolderShareModal,
HomeIcon,
ShareIcon,
},
})
export default class FolderTopMatter extends Mixins(GlobalMixin) {
@ -63,4 +93,19 @@ export default class FolderTopMatter extends Mixins(GlobalMixin) {
}
}
}
</script>
</script>
<style lang="scss" scoped>
.top-matter {
display: flex;
vertical-align: middle;
.right-actions {
margin-right: 40px;
z-index: 50;
@media (max-width: 768px) {
margin-right: 10px;
}
}
}
</style>

View File

@ -186,6 +186,18 @@ export function convertFlags(photo: IPhoto) {
}
}
/**
* Get the path of the folder on folders route
* This function does not check if this is the folder route
*/
export function getFolderRoutePath(basePath: string) {
let path: any = vuerouter.currentRoute.params.path || "/";
path = typeof path === "string" ? path : path.join("/");
path = basePath + "/" + path;
path = path.replace(/\/\/+/, "/"); // Remove double slashes
return path;
}
// Outside for set
const TagDayID = {
START: -(1 << 30),