mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-11 10:06:53 +08:00
293 lines
11 KiB
Vue
293 lines
11 KiB
Vue
<template>
|
|
<div
|
|
v-if="canConnectRows"
|
|
ref="repositoryItemRelationshipsModal"
|
|
@keydown.esc="close"
|
|
id="repositoryItemRelationshipsModal"
|
|
tabindex="-1"
|
|
role="dialog"
|
|
class="modal ">
|
|
<div class="modal-dialog modal-sm" role="document">
|
|
<div class="modal-content w-[400px] m-auto">
|
|
|
|
<!-- header -->
|
|
<div class="modal-header h-[76px] flex !flex-col gap-[6px]">
|
|
|
|
<!-- header title with close icon -->
|
|
<div class="h-[30px] w-full flex flex-row-reverse">
|
|
<i id="close-icon" class="sn-icon sn-icon-close ml-auto cursor-pointer my-auto mx-0" data-dismiss="modal"
|
|
aria-label="Close" @click="close"></i>
|
|
<h4 class="modal-title" id="modal-destroy-team-label">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.header_title') }}
|
|
</h4>
|
|
</div>
|
|
|
|
<!-- header subtitle -->
|
|
<div class="h-10 overflow-hidden break-words text-sn-dark-grey text-sm font-normal leading-5 self-start"
|
|
style="-webkit-box-orient: vertical; -webkit-line-clamp: 2; display: -webkit-box;">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.header_subtitle') }}
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="modal-body flex flex-col gap-6" :class="{ '!pb-3': notification }">
|
|
<!-- inventory -->
|
|
<div class="flex flex-col gap-[7px]">
|
|
<div class="h-5 whitespace-nowrap overflow-auto">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.inventory_section_title') }}</div>
|
|
<div class="h-11">
|
|
<select-search ref="ChangeSelectedInventoryDropdownSelector" :value="selectedInventoryValue"
|
|
:options="inventoryOptions"
|
|
:isLoading="isLoadingInventories"
|
|
:lazyLoadEnabled="true"
|
|
:optionsUrl="inventoriesUrl"
|
|
optionsClassName="inventory-options"
|
|
:placeholder="i18n.t('repositories.item_card.repository_item_relationships_modal.select_inventory_placeholder')"
|
|
:noOptionsPlaceholder="i18n.t('repositories.item_card.repository_item_relationships_modal.select_inventory_no_options_placeholder')"
|
|
:searchPlaceholder="i18n.t('repositories.item_card.repository_item_relationships_modal.select_inventory_placeholder')"
|
|
@update-options="updateInventories"
|
|
@reached-end="fetchInventories"
|
|
@change="changeSelectedInventory"
|
|
></select-search>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- item -->
|
|
<div class="flex flex-col gap-[7px]">
|
|
<div class="h-5 whitespace-nowrap overflow-auto">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.item_section_title') }}</div>
|
|
<div class="h-11">
|
|
<ChecklistSearch
|
|
ref="ChangeSelectedItemChecklistSelector"
|
|
:shouldUpdateWithoutValues="true"
|
|
:lazyLoadEnabled="true"
|
|
:withButtons="false"
|
|
:withEditCursor="false"
|
|
optionsClassName="item-options"
|
|
:optionsUrl="inventoryItemsUrl"
|
|
:options="itemOptions"
|
|
:placeholder="i18n.t('repositories.item_card.repository_item_relationships_modal.select_item_placeholder')"
|
|
:noOptionsPlaceholder="i18n.t('repositories.item_card.repository_item_relationships_modal.select_item_no_options_placeholder')"
|
|
:initialSelectedValues="selectedItemValues"
|
|
:shouldUpdateOnToggleClose="true"
|
|
:params="itemParams"
|
|
@update-options="updateInventoryItems"
|
|
@update="selectedItemValues = $event"
|
|
@reached-end="() => fetchInventoryItems(selectedInventoryValue)"
|
|
:disabled="!this.selectedInventoryValue"
|
|
></ChecklistSearch>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- relationship -->
|
|
<div class="flex flex-col gap-[7px]">
|
|
<div class="h-5 whitespace-nowrap overflow-auto">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.relationship_section_title') }}
|
|
</div>
|
|
<div class="h-11">
|
|
<Select
|
|
ref="ChangeSelectedRelationshipDropdownSelector"
|
|
class="hover:border-sn-sleepy-grey"
|
|
@change="selectedRelationshipValue = $event"
|
|
:value="selectedRelationshipValue"
|
|
:options="[['parent', 'Parent'], ['child', 'Child']]"
|
|
:placeholder="i18n.t('repositories.item_card.repository_item_relationships_modal.select_relationship_placeholder')"
|
|
></Select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notification -->
|
|
<template v-if="notification">
|
|
<hr class="bg-sn-light-grey mb-6 mt-3" />
|
|
<div class="w-full mb-6">
|
|
<div class="flex align-center gap-2.5">
|
|
<img class="w-6 h-6" :src="notificationIconPath" alt="warning" />
|
|
<span class="my-auto">{{ notification.message }}</span>
|
|
</div>
|
|
<div v-html="notification.support_html" class="pl-2.5"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- footer -->
|
|
<div class="modal-footer">
|
|
<div class="flex justify-end gap-4">
|
|
<button class="btn btn-secondary w-[78px] h-10 whitespace-nowrap" @click="close">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.cancel_button') }}
|
|
</button>
|
|
<button class="btn btn-primary w-[59px] h-10 whitespace-nowrap"
|
|
:class="{ 'disabled': !shouldEnableAddButton }" @click="() => addRelation(selectedRelationshipValue)">
|
|
{{ i18n.t('repositories.item_card.repository_item_relationships_modal.add_button') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import SelectSearch from '../shared/select_search.vue';
|
|
import ChecklistSearch from '../shared/checklist_search.vue';
|
|
import Select from '../shared/select.vue';
|
|
|
|
export default {
|
|
name: 'RepositoryItemRelationshipsModal',
|
|
components: {
|
|
'select-search': SelectSearch,
|
|
ChecklistSearch,
|
|
Select
|
|
},
|
|
created() {
|
|
window.repositoryItemRelationshipsModal = this;
|
|
},
|
|
data() {
|
|
return {
|
|
isLoadingInventories: false,
|
|
inventoriesUrl: '',
|
|
inventoryItemsUrl: '',
|
|
createConnectionUrl: '',
|
|
createConnectionUrlValue: '',
|
|
selectedInventoryValue: null,
|
|
selectedItemValues: [],
|
|
selectedRelationshipValue: null,
|
|
inventoryOptions: [],
|
|
itemOptions: [],
|
|
nextInventoriesPage: 1,
|
|
nextItemsPage: 1,
|
|
itemParams: [],
|
|
notification: null,
|
|
notificationIconPath: null,
|
|
canConnectRows: null
|
|
};
|
|
},
|
|
computed: {
|
|
shouldEnableAddButton() {
|
|
return (this.selectedInventoryValue && (this.selectedRelationshipValue !== null) && (this.selectedItemValues.length > 0));
|
|
}
|
|
},
|
|
methods: {
|
|
fetchInventories() {
|
|
if (!this.nextInventoriesPage) return;
|
|
|
|
this.loadingInventories = true;
|
|
$.ajax({
|
|
url: this.inventoriesUrl,
|
|
data: {
|
|
page: this.nextInventoriesPage
|
|
},
|
|
success: (result) => {
|
|
this.inventoryOptions = this.inventoryOptions.concat(result.data.map((val) => [val.id, val.name]));
|
|
this.loadingInventories = false;
|
|
this.nextInventoriesPage = result.next_page;
|
|
}
|
|
});
|
|
},
|
|
fetchInventoryItems(inventoryValue = null) {
|
|
if (!inventoryValue || !this.nextItemsPage) return;
|
|
|
|
this.loadingItems = true;
|
|
$.ajax({
|
|
url: this.inventoryItemsUrl,
|
|
data: {
|
|
page: this.nextItemsPage,
|
|
selected_repository_id: inventoryValue
|
|
},
|
|
success: (result) => {
|
|
this.itemOptions = this.itemOptions.concat(result.data.map((val) => ({ id: val.id, label: val.name })));
|
|
this.loadingItems = false;
|
|
this.nextItemsPage = result.next_page;
|
|
}
|
|
});
|
|
},
|
|
updateInventories(currentOptions, result) {
|
|
this.inventoryOptions = currentOptions.concat(result.data?.map((val) => [val.id, val.name]));
|
|
},
|
|
updateInventoryItems(currentOptions, result) {
|
|
this.itemOptions = currentOptions.concat(result.data.map(({ id, name }) => ({ id, label: name })));
|
|
},
|
|
show(params = {}) {
|
|
const {
|
|
relation,
|
|
optionUrls,
|
|
addRelationCallback,
|
|
notificationIconPath,
|
|
notification,
|
|
canConnectRows
|
|
} = params;
|
|
this.inventoriesUrl = optionUrls.inventories_url;
|
|
this.inventoryItemsUrl = optionUrls.inventory_items_url;
|
|
this.createConnectionUrl = optionUrls.create_url;
|
|
this.addRelationCallback = addRelationCallback;
|
|
this.notificationIconPath = notificationIconPath;
|
|
this.notification = notification;
|
|
this.canConnectRows = canConnectRows;
|
|
this.$nextTick(() => {
|
|
$(this.$refs.repositoryItemRelationshipsModal).modal('show');
|
|
});
|
|
|
|
if (['parent', 'child'].includes(relation)) {
|
|
this.selectedRelationshipValue = relation;
|
|
}
|
|
this.$nextTick(() => {
|
|
this.fetchInventories();
|
|
});
|
|
},
|
|
changeSelectedInventory(value) {
|
|
if (value === this.selectedInventoryValue) return;
|
|
|
|
this.selectedInventoryValue = value;
|
|
this.resetSelectedItemValues();
|
|
this.itemOptions = [];
|
|
this.nextItemsPage = 1;
|
|
if (value) {
|
|
this.loadingItems = true;
|
|
this.itemParams = { selected_repository_id: value };
|
|
}
|
|
this.$nextTick(() => {
|
|
this.fetchInventoryItems(value);
|
|
});
|
|
},
|
|
close() {
|
|
Object.assign(this.$data, {
|
|
selectedInventoryValue: null,
|
|
selectedItemValues: [],
|
|
selectedRelationshipValue: null,
|
|
nextInventoriesPage: 1,
|
|
nextItemsPage: 1,
|
|
inventoriesUrl: '',
|
|
inventoryItemsUrl: '',
|
|
createConnectionUrl: '',
|
|
itemOptions: [],
|
|
inventoryOptions: [],
|
|
itemParams: [],
|
|
canConnectRows: null
|
|
});
|
|
$(this.$refs.repositoryItemRelationshipsModal).modal('hide');
|
|
},
|
|
addRelation(relation) {
|
|
const $this = this;
|
|
$.ajax({
|
|
url: this.createConnectionUrl,
|
|
method: 'POST',
|
|
dataType: 'json',
|
|
data: {
|
|
repository_row_connection: {
|
|
relation: this.selectedRelationshipValue,
|
|
relation_ids: this.selectedItemValues,
|
|
connection_repository_id: this.selectedInventoryValue
|
|
}
|
|
},
|
|
success: (result) => {
|
|
$this.addRelationCallback(result, relation);
|
|
if ($('.dataTable.repository-dataTable')[0]) $('.dataTable.repository-dataTable').DataTable().ajax.reload(null, false);
|
|
}
|
|
});
|
|
this.close();
|
|
},
|
|
resetSelectedItemValues() {
|
|
this.selectedItemValues = [];
|
|
}
|
|
}
|
|
};
|
|
</script>
|