diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 1cb3c6574..92780b3d5 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -65,6 +65,8 @@ class RepositoriesController < ApplicationController results = results.order('LOWER(repository_rows.name) asc').page(params[:page]) + results = results.where.not(id: params[:excluded_ids]) if params[:excluded_ids].present? + render json: { paginated: true, next_page: results.next_page, diff --git a/app/javascript/vue/forms/edit_field.vue b/app/javascript/vue/forms/edit_field.vue index 5ee5505ff..6e87a90f3 100644 --- a/app/javascript/vue/forms/edit_field.vue +++ b/app/javascript/vue/forms/edit_field.vue @@ -86,6 +86,7 @@ import SingleChoiceField from './edit_fields/single_choice.vue'; import TextField from './edit_fields/text.vue'; import MultipleChoiceField from './edit_fields/multiple_choice.vue'; import ActionField from './edit_fields/action.vue'; +import RepositoryRowsField from './edit_fields/repository_rows.vue'; export default { name: 'EditField', @@ -100,7 +101,8 @@ export default { SingleChoiceField, TextField, MultipleChoiceField, - ActionField + ActionField, + RepositoryRowsField }, data() { return { diff --git a/app/javascript/vue/forms/edit_fields/repository_rows.vue b/app/javascript/vue/forms/edit_fields/repository_rows.vue new file mode 100644 index 000000000..b6921f01c --- /dev/null +++ b/app/javascript/vue/forms/edit_fields/repository_rows.vue @@ -0,0 +1,9 @@ + + + diff --git a/app/javascript/vue/forms/field.vue b/app/javascript/vue/forms/field.vue index 0d9cc54b2..5170db4c1 100644 --- a/app/javascript/vue/forms/field.vue +++ b/app/javascript/vue/forms/field.vue @@ -47,6 +47,7 @@ import SingleChoiceField from './fields/single_choice.vue'; import TextField from './fields/text.vue'; import MultipleChoiceField from './fields/multiple_choice.vue'; import ActionField from './fields/action.vue'; +import RepositoryRowsField from './fields/repository_rows.vue'; export default { name: 'ViewField', @@ -64,7 +65,8 @@ export default { SingleChoiceField, TextField, MultipleChoiceField, - ActionField + ActionField, + RepositoryRowsField }, data() { return { diff --git a/app/javascript/vue/forms/fields/modals/row_selector.vue b/app/javascript/vue/forms/fields/modals/row_selector.vue new file mode 100644 index 000000000..458a25be9 --- /dev/null +++ b/app/javascript/vue/forms/fields/modals/row_selector.vue @@ -0,0 +1,65 @@ + + + diff --git a/app/javascript/vue/forms/fields/repository_rows.vue b/app/javascript/vue/forms/fields/repository_rows.vue new file mode 100644 index 000000000..797601355 --- /dev/null +++ b/app/javascript/vue/forms/fields/repository_rows.vue @@ -0,0 +1,85 @@ + + + diff --git a/app/javascript/vue/forms/show.vue b/app/javascript/vue/forms/show.vue index d104d8550..638dda666 100644 --- a/app/javascript/vue/forms/show.vue +++ b/app/javascript/vue/forms/show.vue @@ -158,7 +158,8 @@ export default { { name: this.i18n.t('forms.show.blocks.SingleChoiceField'), type: 'SingleChoiceField' }, { name: this.i18n.t('forms.show.blocks.MultipleChoiceField'), type: 'MultipleChoiceField' }, { name: this.i18n.t('forms.show.blocks.DatetimeField'), type: 'DatetimeField' }, - { name: this.i18n.t('forms.show.blocks.ActionField'), type: 'ActionField' } + { name: this.i18n.t('forms.show.blocks.ActionField'), type: 'ActionField' }, + { name: this.i18n.t('forms.show.blocks.RepositoryRowsField'), type: 'RepositoryRowsField' } ]; }, fieldIcon() { @@ -168,7 +169,8 @@ export default { SingleChoiceField: 'sn-icon-choice-single', MultipleChoiceField: 'sn-icon-choice-multiple', DatetimeField: 'sn-icon-created', - ActionField: 'sn-icon-check' + ActionField: 'sn-icon-check', + RepositoryRowsField: 'sn-icon-inventory' }; } }, diff --git a/app/javascript/vue/shared/repository_row_selector.vue b/app/javascript/vue/shared/repository_row_selector.vue index e56bdf06f..08db8e9bb 100644 --- a/app/javascript/vue/shared/repository_row_selector.vue +++ b/app/javascript/vue/shared/repository_row_selector.vue @@ -6,6 +6,7 @@ :optionsUrl="repositoriesUrl" placeholder="Select inventory" :searchable="true" + :value="selectedRepository" @change="selectedRepository = $event" > @@ -15,12 +16,14 @@ :key="selectedRepository" :disabled="!selectedRepository" :optionsUrl="rowsUrl" - :urlParams="{ repository_id: selectedRepository }" + :urlParams="{ repository_id: selectedRepository, excluded_ids: excludeRows }" + ajaxMethod="post" placeholder="Select item" :multiple="multiple" :withCheckboxes="multiple" :searchable="true" :optionRenderer="itemRowOptionRenderer" + :value="selectedRow" @close="showItemInfo = false" @change="selectedRow= $event" > @@ -63,10 +66,32 @@ export default { multiple: { type: Boolean, default: false + }, + preSelectedRepository: { + type: Number, + default: null + }, + preSelectedRows: { + type: [Array], + default: null + }, + excludeRows: { + type: Array, + default: () => [] } }, created() { this.teamId = document.body.dataset.currentTeamId; + if (this.preSelectedRepository) { + this.selectedRepository = this.preSelectedRepository; + } + if (this.preSelectedRows) { + this.selectedRow = this.preSelectedRows; + } + + this.$nextTick(() => { + this.loading = false; + }); }, mounted() { document.addEventListener('mouseover', this.loadColumnsInfo); @@ -76,11 +101,15 @@ export default { }, watch: { selectedRepository() { + if (this.loading) return; + this.selectedRow = null; this.$emit('repositoryChange', this.selectedRepository); this.$emit('change', this.selectedRow); }, selectedRow() { + if (this.loading) return; + this.$emit('change', this.selectedRow); } }, @@ -103,7 +132,8 @@ export default { teamId: null, showItemInfo: false, hoveredRow: {}, - loadingHoveredRow: false + loadingHoveredRow: false, + loading: true }; }, methods: { diff --git a/app/javascript/vue/shared/select_dropdown.vue b/app/javascript/vue/shared/select_dropdown.vue index 35c09b28d..85fb8273e 100644 --- a/app/javascript/vue/shared/select_dropdown.vue +++ b/app/javascript/vue/shared/select_dropdown.vue @@ -129,7 +129,8 @@ export default { clearable: { type: Boolean, default: false }, tagsView: { type: Boolean, default: false }, urlParams: { type: Object, default: () => ({}) }, - e2eValue: { type: String, default: '' } + e2eValue: { type: String, default: '' }, + ajaxMethod: { type: String, default: 'get' } }, directives: { 'click-outside': vOnClickOutside @@ -369,7 +370,7 @@ export default { fetchOptions() { if (this.optionsUrl) { const params = { query: this.query, page: this.nextPage, ...this.urlParams }; - axios.get(this.optionsUrl, { params }) + axios({ method: this.ajaxMethod, url: this.optionsUrl, data: params }) .then((response) => { if (response.data.paginated) { this.fetchedOptions = [...this.fetchedOptions, ...response.data.data]; diff --git a/app/models/form_repository_rows_field_value.rb b/app/models/form_repository_rows_field_value.rb index 46e975973..b993a47a9 100644 --- a/app/models/form_repository_rows_field_value.rb +++ b/app/models/form_repository_rows_field_value.rb @@ -7,6 +7,12 @@ class FormRepositoryRowsFieldValue < FormFieldValue # adds new snapshots if not yet present self.data ||= [] + # If income data is empty, we need nulify data + if repository_row_ids.blank? + self.data = nil + return + end + removed_repository_row_ids = data.pluck('id') - repository_row_ids existing_repository_row_ids = data.pluck('id') & repository_row_ids diff --git a/config/locales/en.yml b/config/locales/en.yml index 3c9e3a29d..8e3e30819 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1156,6 +1156,9 @@ en: no_block: 'Add your first form block' field_too_long_error: 'Field is too long (maximum number is %{limit} characters)' options_too_many_error: 'Too many options (maximum number is %{limit} options)' + add_items: 'Add items' + add: 'Add' + select_items: 'Select items' validations: response_validation: title: 'Response validation' @@ -1169,6 +1172,7 @@ en: MultipleChoiceField: 'Multiple choice' DatetimeField: 'Date & Time' ActionField: 'Action' + RepositoryRowsField: 'Item' response: submit: 'Submit form' submitted_on: 'Submitted on' @@ -3587,7 +3591,7 @@ en: header: printed_from: "Printed from" print_info: "on %{datetime} by %{full_name}" - forms: + forms: single_choice_html: "(Select one)" multiple_choice_html: "(Select multiple)" protocols_io_import: diff --git a/config/routes.rb b/config/routes.rb index fce72f577..295e44c60 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -209,7 +209,7 @@ Rails.application.routes.draw do defaults: { format: 'json' } post 'actions_toolbar' get :list - get :rows_list + post :rows_list end member do get :export_empty_repository