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);
|
||||
|
||||
function openModal() {
|
||||
if(currentDir.userManagerPermissions) {
|
||||
if(currentDir.organizationFolderResourceId) {
|
||||
router.push({
|
||||
path: '/resource/' + currentDir.organizationFolderResourceId
|
||||
});
|
||||
} else {
|
||||
router.push({
|
||||
path: '/organizationFolder/' + currentDir.organizationFolderId
|
||||
});
|
||||
}
|
||||
|
||||
if(currentDir.organizationFolderResourceId && currentDir.organizationFolderResourceUpdatePermissions) {
|
||||
router.push({
|
||||
path: '/resource/' + currentDir.organizationFolderResourceId
|
||||
});
|
||||
modalOpen.value = true;
|
||||
} else if(currentDir.organizationFolderId && currentDir.organizationFolderUpdatePermissions) {
|
||||
router.push({
|
||||
path: '/organizationFolder/' + currentDir.organizationFolderId
|
||||
});
|
||||
modalOpen.value = true;
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +31,7 @@ function openModal() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="currentDir.userManagerPermissions" class="toolbar">
|
||||
<div v-if="currentDir.organizationFolderUpdatePermissions || currentDir.organizationFolderResourceUpdatePermissions" class="toolbar">
|
||||
<NcButton :disabled="currentDir.loading"
|
||||
type="primary"
|
||||
@click="openModal">
|
||||
|
|
14
src/api.js
14
src/api.js
|
@ -14,6 +14,17 @@ var PrincipalTypes = {
|
|||
ROLE: 3,
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {number} ResourceType
|
||||
**/
|
||||
|
||||
/**
|
||||
* @enum {ResourceType}
|
||||
*/
|
||||
var ResourceTypes = {
|
||||
FOLDER: "folder",
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {number} ResourceMemberPermissionLevel
|
||||
**/
|
||||
|
@ -38,6 +49,8 @@ var ResourceMemberPermissionLevels = {
|
|||
* membersAclPermission: number
|
||||
* managersAclPermission: number
|
||||
* inheritedAclPermission: number
|
||||
* members: Array<ResourceMember>|undefined
|
||||
* subResources: Array<Resource>|undefined
|
||||
* }} FolderResource
|
||||
*
|
||||
* @typedef {(FolderResource)} Resource
|
||||
|
@ -69,6 +82,7 @@ axios.defaults.baseURL = generateUrl("/apps/organization_folders")
|
|||
export default {
|
||||
PrincipalTypes,
|
||||
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 v-if="!loading && !members.length">
|
||||
<td colspan="4" style="grid-column-start: 1; grid-column-end: 5">
|
||||
<NcEmptyContent title="Keine Mitglieder" />
|
||||
<NcEmptyContent name="Keine Mitglieder" />
|
||||
</td>
|
||||
</tr>
|
||||
<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 ResourceSettings from "./views/ResourceSettings.vue";
|
||||
import OrganizationFolderSettings from "./views/OrganizationFolderSettings.vue";
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
const router = new Router({
|
||||
mode: 'abstract',
|
||||
routes: [
|
||||
{
|
||||
path: "/organizationFolder/:organizationFolderId",
|
||||
name: "organizationFolder-settings",
|
||||
component: OrganizationFolderSettings,
|
||||
props: (route) => (
|
||||
{
|
||||
organizationFolderId: Number.parseInt(route.params.organizationFolderId, 10) || undefined,
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/resource/:resourceId",
|
||||
name: "resource-settings",
|
||||
|
|
|
@ -8,8 +8,9 @@ export const useCurrentDirStore = defineStore("currentDir", {
|
|||
loading: false,
|
||||
path: "",
|
||||
organizationFolderId: null,
|
||||
organizationFolderUpdatePermissions: null,
|
||||
organizationFolderResourceId: null,
|
||||
userManagerPermissions: null,
|
||||
organizationFolderResourceUpdatePermissions: null,
|
||||
}),
|
||||
actions: {
|
||||
/**
|
||||
|
@ -24,8 +25,9 @@ export const useCurrentDirStore = defineStore("currentDir", {
|
|||
let { fileInfo } = await getFolderProperties(path)
|
||||
.catch(() => {
|
||||
this.organizationFolderId = false;
|
||||
this.organizationFolderUpdatePermissions = false,
|
||||
this.organizationFolderResourceId = false;
|
||||
this.userManagerPermissions = false;
|
||||
this.organizationFolderResourceUpdatePermissions = false;
|
||||
this.loading = false;
|
||||
});
|
||||
|
||||
|
@ -33,12 +35,14 @@ export const useCurrentDirStore = defineStore("currentDir", {
|
|||
|
||||
if(fileInfo) {
|
||||
this.organizationFolderId = fileInfo.organizationFolderId;
|
||||
this.organizationFolderUpdatePermissions = fileInfo.organizationFolderUpdatePermissions;
|
||||
this.organizationFolderResourceId = fileInfo.organizationFolderResourceId;
|
||||
this.userManagerPermissions = fileInfo.userManagerPermissions;
|
||||
this.organizationFolderResourceUpdatePermissions = fileInfo.organizationFolderResourceUpdatePermissions;
|
||||
} else {
|
||||
this.organizationFolderId = false;
|
||||
this.organizationFolderUpdatePermissions = false;
|
||||
this.organizationFolderResourceId = false;
|
||||
this.userManagerPermissions = false;
|
||||
this.organizationFolderResourceUpdatePermissions = 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 Permissions from "../components/Permissions/index.js";
|
||||
import ConfirmDeleteDialog from "../components/ConfirmDeleteDialog.vue";
|
||||
import ResourceList from "../components/ResourceList.vue";
|
||||
import CreateResourceButton from "../components/CreateResourceButton.vue";
|
||||
import ModalView from '../ModalView.vue';
|
||||
import api from "../api.js";
|
||||
import { useRouter } from 'vue2-helpers/vue-router';
|
||||
import { validResourceName } from "../helpers/validation.js";
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -87,12 +90,38 @@ api.getOrganizationProviders().then((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>
|
||||
|
||||
<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>
|
||||
<div class="resource-general-settings">
|
||||
<NcTextField :value.sync="currentResourceName"
|
||||
|
@ -165,10 +194,15 @@ const validResourceMemberPrincipalTypes = api.PrincipalTypes;
|
|||
</template>
|
||||
</ConfirmDeleteDialog>
|
||||
</div>
|
||||
<div class="header-button-group">
|
||||
<h3>Unter-Resourcen</h3>
|
||||
<CreateResourceButton />
|
||||
</div>
|
||||
<ResourceList :resources="resource?.subResources" @click:resource="subResourceClicked" />
|
||||
</ModalView>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
.name-input-group {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
@ -184,9 +218,11 @@ const validResourceMemberPrincipalTypes = api.PrincipalTypes;
|
|||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.resource-active-button >>> .checkbox-radio-switch__label {
|
||||
/* Add primary background color like other buttons */
|
||||
background-color: var(--color-primary-light);
|
||||
.resource-active-button {
|
||||
::v-deep .checkbox-radio-switch__label {
|
||||
/* Add primary background color like other buttons */
|
||||
background-color: var(--color-primary-light);
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
|
@ -198,4 +234,17 @@ h3 {
|
|||
margin-top: 24px;
|
||||
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>
|
Loading…
Reference in a new issue