mirror of
https://github.com/verdigado/organization_folders.git
synced 2024-12-06 11:22:41 +01:00
started implementing organizationFolder-settings view, subresources are not listed in resource-settings view
This commit is contained in:
parent
da04604856
commit
225072bff7
9 changed files with 239 additions and 23 deletions
|
@ -15,17 +15,15 @@ const currentDir = useCurrentDirStore();
|
||||||
const modalOpen = ref(false);
|
const modalOpen = ref(false);
|
||||||
|
|
||||||
function openModal() {
|
function openModal() {
|
||||||
if(currentDir.userManagerPermissions) {
|
if(currentDir.organizationFolderResourceId && currentDir.organizationFolderResourceUpdatePermissions) {
|
||||||
if(currentDir.organizationFolderResourceId) {
|
router.push({
|
||||||
router.push({
|
path: '/resource/' + currentDir.organizationFolderResourceId
|
||||||
path: '/resource/' + currentDir.organizationFolderResourceId
|
});
|
||||||
});
|
modalOpen.value = true;
|
||||||
} else {
|
} else if(currentDir.organizationFolderId && currentDir.organizationFolderUpdatePermissions) {
|
||||||
router.push({
|
router.push({
|
||||||
path: '/organizationFolder/' + currentDir.organizationFolderId
|
path: '/organizationFolder/' + currentDir.organizationFolderId
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
modalOpen.value = true;
|
modalOpen.value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +31,7 @@ function openModal() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="currentDir.userManagerPermissions" class="toolbar">
|
<div v-if="currentDir.organizationFolderUpdatePermissions || currentDir.organizationFolderResourceUpdatePermissions" class="toolbar">
|
||||||
<NcButton :disabled="currentDir.loading"
|
<NcButton :disabled="currentDir.loading"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="openModal">
|
@click="openModal">
|
||||||
|
|
14
src/api.js
14
src/api.js
|
@ -14,6 +14,17 @@ var PrincipalTypes = {
|
||||||
ROLE: 3,
|
ROLE: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {number} ResourceType
|
||||||
|
**/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {ResourceType}
|
||||||
|
*/
|
||||||
|
var ResourceTypes = {
|
||||||
|
FOLDER: "folder",
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {number} ResourceMemberPermissionLevel
|
* @typedef {number} ResourceMemberPermissionLevel
|
||||||
**/
|
**/
|
||||||
|
@ -38,6 +49,8 @@ var ResourceMemberPermissionLevels = {
|
||||||
* membersAclPermission: number
|
* membersAclPermission: number
|
||||||
* managersAclPermission: number
|
* managersAclPermission: number
|
||||||
* inheritedAclPermission: number
|
* inheritedAclPermission: number
|
||||||
|
* members: Array<ResourceMember>|undefined
|
||||||
|
* subResources: Array<Resource>|undefined
|
||||||
* }} FolderResource
|
* }} FolderResource
|
||||||
*
|
*
|
||||||
* @typedef {(FolderResource)} Resource
|
* @typedef {(FolderResource)} Resource
|
||||||
|
@ -69,6 +82,7 @@ axios.defaults.baseURL = generateUrl("/apps/organization_folders")
|
||||||
export default {
|
export default {
|
||||||
PrincipalTypes,
|
PrincipalTypes,
|
||||||
ResourceMemberPermissionLevels,
|
ResourceMemberPermissionLevels,
|
||||||
|
ResourceTypes,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
26
src/components/CreateResourceButton.vue
Normal file
26
src/components/CreateResourceButton.vue
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { NcActions, NcActionInput } from '@nextcloud/vue';
|
||||||
|
|
||||||
|
import Folder from "vue-material-design-icons/Folder.vue";
|
||||||
|
import Plus from "vue-material-design-icons/Plus.vue";
|
||||||
|
|
||||||
|
import api from "../api.js";
|
||||||
|
import { validResourceName } from "../helpers/validation.js";
|
||||||
|
|
||||||
|
const emit = defineEmits(["create"]);
|
||||||
|
|
||||||
|
const newFolderResourceName = ref("");
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<NcActions type="secondary">
|
||||||
|
<template #icon>
|
||||||
|
<Plus :size="20" />
|
||||||
|
</template>
|
||||||
|
<NcActionInput v-model="newFolderResourceName" :label-outside="true" label="Ordner hinzufügen" @submit="emit('create', api.ResourceTypes.FOLDER, newFolderResourceName)">
|
||||||
|
<template #icon>
|
||||||
|
<Folder :size="20" />
|
||||||
|
</template>
|
||||||
|
</NcActionInput>
|
||||||
|
</NcActions>
|
||||||
|
</template>
|
|
@ -113,7 +113,7 @@ const deleteMember = (memberId) => {
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="!loading && !members.length">
|
<tr v-if="!loading && !members.length">
|
||||||
<td colspan="4" style="grid-column-start: 1; grid-column-end: 5">
|
<td colspan="4" style="grid-column-start: 1; grid-column-end: 5">
|
||||||
<NcEmptyContent title="Keine Mitglieder" />
|
<NcEmptyContent name="Keine Mitglieder" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<MemberListItem v-for="member in members"
|
<MemberListItem v-for="member in members"
|
||||||
|
|
87
src/components/ResourceList.vue
Normal file
87
src/components/ResourceList.vue
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { NcListItem, NcTextField, NcEmptyContent } from '@nextcloud/vue';
|
||||||
|
|
||||||
|
import Magnify from "vue-material-design-icons/Magnify.vue";
|
||||||
|
import CheckboxBlankCircle from "vue-material-design-icons/CheckboxBlankCircle.vue";
|
||||||
|
import Folder from "vue-material-design-icons/Folder.vue";
|
||||||
|
import FolderOff from "vue-material-design-icons/FolderOff.vue";
|
||||||
|
|
||||||
|
import api from "../api.js";
|
||||||
|
|
||||||
|
const emit = defineEmits(["click:resource"]);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
resources: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
enableSearch: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const search = ref("");
|
||||||
|
|
||||||
|
const filteredResources = computed(() => props.resources.filter((g) => g.name.toLowerCase().includes(search.value.toLowerCase())))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<NcTextField v-if="props.enableSearch"
|
||||||
|
:value.sync="search"
|
||||||
|
label="Suche..."
|
||||||
|
class="search-input"
|
||||||
|
trailing-button-icon="close"
|
||||||
|
:show-trailing-button="search !== ''"
|
||||||
|
@trailing-button-click="search = ''">
|
||||||
|
<Magnify :size="16" />
|
||||||
|
</NcTextField>
|
||||||
|
<NcEmptyContent v-if="resources.length === 0" name="Keine Unter-Resourcen vorhanden">
|
||||||
|
<template #icon>
|
||||||
|
<FolderOff />
|
||||||
|
</template>
|
||||||
|
</NcEmptyContent>
|
||||||
|
<ul v-else>
|
||||||
|
<NcListItem v-for="resource in filteredResources"
|
||||||
|
:key="resource.id"
|
||||||
|
class="resource-list material_you"
|
||||||
|
:name="resource.name"
|
||||||
|
:linkAriaLabel="resource.name"
|
||||||
|
:force-display-actions="true"
|
||||||
|
@click="() => emit('click:resource', resource)">
|
||||||
|
<template #icon>
|
||||||
|
<Folder v-if="resource.type === api.ResourceTypes.FOLDER" :size="44" />
|
||||||
|
</template>
|
||||||
|
<template #indicator>
|
||||||
|
<CheckboxBlankCircle v-tooltip="resource.active ? 'aktiviert' : 'nicht aktiviert'" :size="16" :fill-color="resource.active ? 'var(--color-primary)' : '#333'" />
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
actions
|
||||||
|
</template>
|
||||||
|
</NcListItem>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.search-input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #666;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* center the indicator icon for folder active state " */
|
||||||
|
.resource-list {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .resource-list .line-two__additional_elements {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(50% - 8px);
|
||||||
|
right: 25px;
|
||||||
|
margin: 0;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,12 +2,23 @@ import Vue from "vue";
|
||||||
import Router from "vue-router";
|
import Router from "vue-router";
|
||||||
|
|
||||||
import ResourceSettings from "./views/ResourceSettings.vue";
|
import ResourceSettings from "./views/ResourceSettings.vue";
|
||||||
|
import OrganizationFolderSettings from "./views/OrganizationFolderSettings.vue";
|
||||||
|
|
||||||
Vue.use(Router);
|
Vue.use(Router);
|
||||||
|
|
||||||
const router = new Router({
|
const router = new Router({
|
||||||
mode: 'abstract',
|
mode: 'abstract',
|
||||||
routes: [
|
routes: [
|
||||||
|
{
|
||||||
|
path: "/organizationFolder/:organizationFolderId",
|
||||||
|
name: "organizationFolder-settings",
|
||||||
|
component: OrganizationFolderSettings,
|
||||||
|
props: (route) => (
|
||||||
|
{
|
||||||
|
organizationFolderId: Number.parseInt(route.params.organizationFolderId, 10) || undefined,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/resource/:resourceId",
|
path: "/resource/:resourceId",
|
||||||
name: "resource-settings",
|
name: "resource-settings",
|
||||||
|
|
|
@ -8,8 +8,9 @@ export const useCurrentDirStore = defineStore("currentDir", {
|
||||||
loading: false,
|
loading: false,
|
||||||
path: "",
|
path: "",
|
||||||
organizationFolderId: null,
|
organizationFolderId: null,
|
||||||
|
organizationFolderUpdatePermissions: null,
|
||||||
organizationFolderResourceId: null,
|
organizationFolderResourceId: null,
|
||||||
userManagerPermissions: null,
|
organizationFolderResourceUpdatePermissions: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +25,9 @@ export const useCurrentDirStore = defineStore("currentDir", {
|
||||||
let { fileInfo } = await getFolderProperties(path)
|
let { fileInfo } = await getFolderProperties(path)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.organizationFolderId = false;
|
this.organizationFolderId = false;
|
||||||
|
this.organizationFolderUpdatePermissions = false,
|
||||||
this.organizationFolderResourceId = false;
|
this.organizationFolderResourceId = false;
|
||||||
this.userManagerPermissions = false;
|
this.organizationFolderResourceUpdatePermissions = false;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,12 +35,14 @@ export const useCurrentDirStore = defineStore("currentDir", {
|
||||||
|
|
||||||
if(fileInfo) {
|
if(fileInfo) {
|
||||||
this.organizationFolderId = fileInfo.organizationFolderId;
|
this.organizationFolderId = fileInfo.organizationFolderId;
|
||||||
|
this.organizationFolderUpdatePermissions = fileInfo.organizationFolderUpdatePermissions;
|
||||||
this.organizationFolderResourceId = fileInfo.organizationFolderResourceId;
|
this.organizationFolderResourceId = fileInfo.organizationFolderResourceId;
|
||||||
this.userManagerPermissions = fileInfo.userManagerPermissions;
|
this.organizationFolderResourceUpdatePermissions = fileInfo.organizationFolderResourceUpdatePermissions;
|
||||||
} else {
|
} else {
|
||||||
this.organizationFolderId = false;
|
this.organizationFolderId = false;
|
||||||
|
this.organizationFolderUpdatePermissions = false;
|
||||||
this.organizationFolderResourceId = false;
|
this.organizationFolderResourceId = false;
|
||||||
this.userManagerPermissions = false;
|
this.organizationFolderResourceUpdatePermissions = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
27
src/views/OrganizationFolderSettings.vue
Normal file
27
src/views/OrganizationFolderSettings.vue
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
import ModalView from '../ModalView.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
organizationFolderId: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<ModalView
|
||||||
|
:has-back-button="false"
|
||||||
|
:has-next-step-button="false"
|
||||||
|
:has-last-step-button="false"
|
||||||
|
:title="'Organization Folder Settings'"
|
||||||
|
:loading="loading"
|
||||||
|
v-slot="">
|
||||||
|
<h3>Eigenschaften</h3>
|
||||||
|
<p>{{ props.organizationFolderId }}</p>
|
||||||
|
</ModalView>
|
||||||
|
</template>
|
|
@ -9,8 +9,11 @@ import Delete from "vue-material-design-icons/Delete.vue";
|
||||||
import ResourceMembersList from "../components/MemberList/ResourceMembersList.vue";
|
import ResourceMembersList from "../components/MemberList/ResourceMembersList.vue";
|
||||||
import Permissions from "../components/Permissions/index.js";
|
import Permissions from "../components/Permissions/index.js";
|
||||||
import ConfirmDeleteDialog from "../components/ConfirmDeleteDialog.vue";
|
import ConfirmDeleteDialog from "../components/ConfirmDeleteDialog.vue";
|
||||||
|
import ResourceList from "../components/ResourceList.vue";
|
||||||
|
import CreateResourceButton from "../components/CreateResourceButton.vue";
|
||||||
import ModalView from '../ModalView.vue';
|
import ModalView from '../ModalView.vue';
|
||||||
import api from "../api.js";
|
import api from "../api.js";
|
||||||
|
import { useRouter } from 'vue2-helpers/vue-router';
|
||||||
import { validResourceName } from "../helpers/validation.js";
|
import { validResourceName } from "../helpers/validation.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -87,12 +90,38 @@ api.getOrganizationProviders().then((providers) => {
|
||||||
organizationProviders.value = providers;
|
organizationProviders.value = providers;
|
||||||
});
|
});
|
||||||
|
|
||||||
const validResourceMemberPrincipalTypes = api.PrincipalTypes;
|
const router = useRouter();
|
||||||
|
|
||||||
|
const subResourceClicked = (resource) => {
|
||||||
|
router.push({
|
||||||
|
path: '/resource/' + resource.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const backButtonClicked = () => {
|
||||||
|
if(resource.value?.parentResource) {
|
||||||
|
router.push({
|
||||||
|
path: '/resource/' + resource.value.parentResource,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
router.push({
|
||||||
|
path: '/organizationFolder/' + resource.value.organizationFolderId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ModalView :has-back-button="true" :has-next-step-button="false" :has-last-step-button="false" :title="'Resource Settings'" :loading="loading" v-slot="">
|
<ModalView
|
||||||
|
:has-back-button="true"
|
||||||
|
:has-next-step-button="false"
|
||||||
|
:has-last-step-button="false"
|
||||||
|
:title="'Resource Settings'"
|
||||||
|
:loading="loading"
|
||||||
|
v-slot=""
|
||||||
|
@back-button-pressed="backButtonClicked">
|
||||||
<h3>Eigenschaften</h3>
|
<h3>Eigenschaften</h3>
|
||||||
<div class="resource-general-settings">
|
<div class="resource-general-settings">
|
||||||
<NcTextField :value.sync="currentResourceName"
|
<NcTextField :value.sync="currentResourceName"
|
||||||
|
@ -165,10 +194,15 @@ const validResourceMemberPrincipalTypes = api.PrincipalTypes;
|
||||||
</template>
|
</template>
|
||||||
</ConfirmDeleteDialog>
|
</ConfirmDeleteDialog>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="header-button-group">
|
||||||
|
<h3>Unter-Resourcen</h3>
|
||||||
|
<CreateResourceButton />
|
||||||
|
</div>
|
||||||
|
<ResourceList :resources="resource?.subResources" @click:resource="subResourceClicked" />
|
||||||
</ModalView>
|
</ModalView>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.name-input-group {
|
.name-input-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
@ -184,9 +218,11 @@ const validResourceMemberPrincipalTypes = api.PrincipalTypes;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resource-active-button >>> .checkbox-radio-switch__label {
|
.resource-active-button {
|
||||||
/* Add primary background color like other buttons */
|
::v-deep .checkbox-radio-switch__label {
|
||||||
background-color: var(--color-primary-light);
|
/* Add primary background color like other buttons */
|
||||||
|
background-color: var(--color-primary-light);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
@ -198,4 +234,17 @@ h3 {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-button-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 10px;
|
||||||
|
margin-top: 24px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in a new issue