Add options for create/select (#5301)

* Hide add/select based on permissions

Fixes #4874

* Add enable create/select options to interfaces
This commit is contained in:
Rijk van Zanten
2021-04-27 15:13:22 -04:00
committed by GitHub
parent f5f6f325f7
commit 451cdac8ef
7 changed files with 219 additions and 18 deletions

View File

@@ -39,8 +39,8 @@
</v-list>
<div class="actions" v-if="!disabled">
<v-button class="new" @click="editModalActive = true">{{ $t('create_new') }}</v-button>
<v-button class="existing" @click="selectModalActive = true">
<v-button v-if="enableCreate && createAllowed" @click="editModalActive = true">{{ $t('create_new') }}</v-button>
<v-button v-if="enableSelect && selectAllowed" @click="selectModalActive = true">
{{ $t('add_existing') }}
</v-button>
</div>
@@ -85,6 +85,7 @@ import useSelection from './use-selection';
import useSort from './use-sort';
import { getFieldsFromTemplate } from '@/utils/get-fields-from-template';
import adjustFieldsForDisplays from '@/utils/adjust-fields-for-displays';
import { usePermissionsStore, useUserStore } from '@/stores';
export default defineComponent({
components: { DrawerItem, DrawerCollection, Draggable },
@@ -113,8 +114,19 @@ export default defineComponent({
type: Boolean,
default: false,
},
enableCreate: {
type: Boolean,
default: true,
},
enableSelect: {
type: Boolean,
default: true,
},
},
setup(props, { emit }) {
const permissionsStore = usePermissionsStore();
const userStore = useUserStore();
const { value, collection, field } = toRefs(props);
const { junction, junctionCollection, relation, relationCollection, relationInfo } = useRelation(collection, field);
@@ -173,9 +185,10 @@ export default defineComponent({
} = useEdit(value, relationInfo, emitter);
const { stageSelection, selectModalActive, selectionFilters } = useSelection(value, items, relationInfo, emitter);
const { sort, sortItems, sortedItems } = useSort(relationInfo, fields, items, emitter);
const { createAllowed, selectAllowed } = usePermissions();
return {
junction,
relation,
@@ -201,11 +214,46 @@ export default defineComponent({
sortItems,
sortedItems,
templateWithDefaults,
createAllowed,
selectAllowed,
};
function emitter(newVal: any[] | null) {
emit('input', newVal);
}
function usePermissions() {
const createAllowed = computed(() => {
const admin = userStore.state?.currentUser?.role.admin_access === true;
if (admin) return true;
const hasJunctionPermissions = !!permissionsStore.state.permissions.find(
(permission) =>
permission.action === 'create' && permission.collection === junctionCollection.value.collection
);
const hasRelatedPermissions = !!permissionsStore.state.permissions.find(
(permission) =>
permission.action === 'create' && permission.collection === relationCollection.value.collection
);
return hasJunctionPermissions && hasRelatedPermissions;
});
const selectAllowed = computed(() => {
const admin = userStore.state?.currentUser?.role.admin_access === true;
if (admin) return true;
const hasJunctionPermissions = !!permissionsStore.state.permissions.find(
(permission) =>
permission.action === 'create' && permission.collection === junctionCollection.value.collection
);
return hasJunctionPermissions;
});
return { createAllowed, selectAllowed };
}
},
});
</script>
@@ -217,10 +265,10 @@ export default defineComponent({
.actions {
margin-top: 12px;
}
.existing {
margin-left: 12px;
.v-button + .v-button {
margin-left: 12px;
}
}
.deselect {

View File

@@ -15,6 +15,16 @@
"
/>
</div>
<div class="field half-left">
<p class="type-label">{{ $t('creating_items') }}</p>
<v-checkbox block :label="$t('enable_create_button')" v-model="enableCreate" />
</div>
<div class="field half-right">
<p class="type-label">{{ $t('selecting_items') }}</p>
<v-checkbox block :label="$t('enable_select_button')" v-model="enableSelect" />
</div>
</div>
</template>
@@ -65,6 +75,30 @@ export default defineComponent({
},
});
const enableCreate = computed({
get() {
return props.value?.enableCreate ?? true;
},
set(val: boolean) {
emit('input', {
...(props.value || {}),
enableCreate: val,
});
},
});
const enableSelect = computed({
get() {
return props.value?.enableSelect ?? true;
},
set(val: boolean) {
emit('input', {
...(props.value || {}),
enableSelect: val,
});
},
});
const junctionCollection = computed(() => {
if (!props.fieldData || !props.relations || props.relations.length === 0) return null;
const { field } = props.fieldData;
@@ -80,7 +114,7 @@ export default defineComponent({
return collectionsStore.getCollection(junctionCollection.value);
});
return { template, junctionCollection, junctionCollectionInfo };
return { template, enableCreate, enableSelect, junctionCollection, junctionCollectionInfo };
},
});
</script>

View File

@@ -28,19 +28,22 @@
v-for="item in sortedItems"
:key="item.id"
block
:disabled="disabled || updateAllowed === false"
@click="editItem(item)"
>
<v-icon v-if="relation.sort_field" name="drag_handle" class="drag-handle" left @click.stop="() => {}" />
<render-template :collection="relation.many_collection" :item="item" :template="templateWithDefaults" />
<div class="spacer" />
<v-icon v-if="!disabled" name="close" @click.stop="deleteItem(item)" />
<v-icon v-if="!disabled && updateAllowed" name="close" @click.stop="deleteItem(item)" />
</v-list-item>
</draggable>
</v-list>
<div class="actions" v-if="!disabled">
<v-button class="new" @click="currentlyEditing = '+'">{{ $t('create_new') }}</v-button>
<v-button class="existing" @click="selectModalActive = true">
<v-button v-if="enableCreate && createAllowed && updateAllowed" @click="currentlyEditing = '+'">
{{ $t('create_new') }}
</v-button>
<v-button v-if="enableSelect && updateAllowed" @click="selectModalActive = true">
{{ $t('add_existing') }}
</v-button>
</div>
@@ -72,7 +75,7 @@
import { defineComponent, ref, computed, watch, PropType } from '@vue/composition-api';
import api from '@/api';
import useCollection from '@/composables/use-collection';
import { useCollectionsStore, useRelationsStore, useFieldsStore } from '@/stores/';
import { useCollectionsStore, useRelationsStore, useFieldsStore, usePermissionsStore, useUserStore } from '@/stores/';
import DrawerItem from '@/views/private/components/drawer-item';
import DrawerCollection from '@/views/private/components/drawer-collection';
import { Filter, Field } from '@/types';
@@ -110,11 +113,21 @@ export default defineComponent({
type: Boolean,
default: false,
},
enableCreate: {
type: Boolean,
default: true,
},
enableSelect: {
type: Boolean,
default: true,
},
},
setup(props, { emit }) {
const relationsStore = useRelationsStore();
const collectionsStore = useCollectionsStore();
const fieldsStore = useFieldsStore();
const permissionsStore = usePermissionsStore();
const userStore = useUserStore();
const { relation, relatedCollection, relatedPrimaryKeyField } = useRelation();
@@ -131,6 +144,8 @@ export default defineComponent({
const { stageSelection, selectModalActive, selectionFilters } = useSelection();
const { sort, sortItems, sortedItems } = useSort();
const { createAllowed, updateAllowed } = usePermissions();
return {
relation,
loading,
@@ -151,6 +166,8 @@ export default defineComponent({
get,
getItemFromIndex,
templateWithDefaults,
createAllowed,
updateAllowed,
};
function getItemFromIndex(index: number) {
@@ -426,6 +443,28 @@ export default defineComponent({
const fields = fieldsStore.getFieldsForCollection(relatedCollection.value.collection);
return fields.slice(0, 3).map((field: Field) => field.field);
}
function usePermissions() {
const createAllowed = computed(() => {
const admin = userStore.state?.currentUser?.role.admin_access === true;
if (admin) return true;
return !!permissionsStore.state.permissions.find(
(permission) => permission.action === 'create' && permission.collection === relatedCollection.value.collection
);
});
const updateAllowed = computed(() => {
const admin = userStore.state?.currentUser?.role.admin_access === true;
if (admin) return true;
return !!permissionsStore.state.permissions.find(
(permission) => permission.action === 'update' && permission.collection === relatedCollection.value.collection
);
});
return { createAllowed, updateAllowed };
}
},
});
</script>
@@ -437,10 +476,10 @@ export default defineComponent({
.actions {
margin-top: 8px;
}
.existing {
margin-left: 8px;
.v-button + .v-button {
margin-left: 8px;
}
}
.deselect {

View File

@@ -15,6 +15,16 @@
"
/>
</div>
<div class="field half-left">
<p class="type-label">{{ $t('creating_items') }}</p>
<v-checkbox block :label="$t('enable_create_button')" v-model="enableCreate" />
</div>
<div class="field half-right">
<p class="type-label">{{ $t('selecting_items') }}</p>
<v-checkbox block :label="$t('enable_select_button')" v-model="enableSelect" />
</div>
</div>
</template>
@@ -65,6 +75,30 @@ export default defineComponent({
},
});
const enableCreate = computed({
get() {
return props.value?.enableCreate ?? true;
},
set(val: boolean) {
emit('input', {
...(props.value || {}),
enableCreate: val,
});
},
});
const enableSelect = computed({
get() {
return props.value?.enableSelect ?? true;
},
set(val: boolean) {
emit('input', {
...(props.value || {}),
enableSelect: val,
});
},
});
const relatedCollection = computed(() => {
if (!props.fieldData || !props.relations || props.relations.length === 0) return null;
const { field } = props.fieldData;
@@ -79,7 +113,7 @@ export default defineComponent({
return collectionsStore.getCollection(relatedCollection.value);
});
return { template, relatedCollection, relatedCollectionInfo };
return { template, enableCreate, enableSelect, relatedCollection, relatedCollectionInfo };
},
});
</script>

View File

@@ -7,6 +7,16 @@
<p class="type-label">{{ $t('interfaces.many-to-one.display_template') }}</p>
<v-field-template :collection="collection" v-model="template" :depth="1"></v-field-template>
</div>
<div class="field half-left">
<p class="type-label">{{ $t('creating_items') }}</p>
<v-checkbox block :label="$t('enable_create_button')" v-model="enableCreate" />
</div>
<div class="field half-right">
<p class="type-label">{{ $t('selecting_items') }}</p>
<v-checkbox block :label="$t('enable_select_button')" v-model="enableSelect" />
</div>
</div>
</template>
@@ -46,7 +56,31 @@ export default defineComponent({
},
});
return { template };
const enableCreate = computed({
get() {
return props.value?.enableCreate ?? true;
},
set(val: boolean) {
emit('input', {
...(props.value || {}),
enableCreate: val,
});
},
});
const enableSelect = computed({
get() {
return props.value?.enableSelect ?? true;
},
set(val: boolean) {
emit('input', {
...(props.value || {}),
enableSelect: val,
});
},
});
return { template, enableCreate, enableSelect };
},
});
</script>

View File

@@ -18,8 +18,8 @@
/>
<div class="actions" v-if="!disabled">
<v-button class="new" @click="addNewActive = true">{{ $t('create_new') }}</v-button>
<v-button class="existing" @click="selectDrawer = true">
<v-button v-if="enableCreate" @click="addNewActive = true">{{ $t('create_new') }}</v-button>
<v-button v-if="enableSelect" @click="selectDrawer = true">
{{ $t('add_existing') }}
</v-button>
</div>
@@ -88,6 +88,14 @@ export default defineComponent({
type: [String, Number],
default: undefined,
},
enableCreate: {
type: Boolean,
default: true,
},
enableSelect: {
type: Boolean,
default: true,
},
},
setup(props, { emit }) {
const relationsStore = useRelationsStore();