Skip to content

Commit

Permalink
add workaround for project dropdown gaining auto focus
Browse files Browse the repository at this point in the history
Signed-off-by: Swikriti Tripathi <swikriti808@gmail.com>
  • Loading branch information
SwikritiT committed Oct 31, 2023
1 parent ce209ae commit 1433dbb
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 125 deletions.
1 change: 1 addition & 0 deletions src/components/tab/SearchInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
</div>
<CreateWorkPackageModal
v-if="!isSmartPicker"
ref="testRef"
:show-modal="isCreateWorkpackageModalVisible"
data-test-id="create-workpackage-modal"
@create-work-package="onCreateWorkPackageEvent"
Expand Down
266 changes: 141 additions & 125 deletions src/views/CreateWorkPackageModal.vue
Original file line number Diff line number Diff line change
@@ -1,136 +1,141 @@
<template>
<NcModal v-if="openModal"
ref="createWorkPackageModalRef"
class="create-workpackage-modal"
:can-close="true"
:out-transition="true"
@close="closeModal">
<h2 class="create-workpackage-modal--title">
{{ t('integration_openproject', 'Create and link a new work package') }}
</h2>
<div class="create-workpackage-form-wrapper">
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Project *') }}
</div>
<NcSelect ref="createWorkPackageInput"
class="create-workpackage-form--select"
input-id="createWorkPackageInput"
data-test-id="available-projects"
:placeholder="t('integration_openproject', 'Select a project')"
:options="mappedNodes"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="project.label"
@option:selected="onSelectProject">
<template #option="{ label, relation, counter }">
<span v-if="relation === 'child'" :style="{paddingLeft: counter + 'em' }" />
<span>{{ label }}</span>
</template>
<template #no-options>
{{ t('integration_openproject', 'Please link a project to this nextcloud storage') }}
</template>
</NcSelect>
<p v-if="error.error && error.attribute === 'project'" class="validation-error">
{{ error.message }}
</p>
<p v-else-if="error.error && error.multipleErrors.project" class="validation-error multiple-error-project">
{{ error.multipleErrors.project }}
</p>
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Subject *') }}
</div>
<NcInputField :value="subject"
class="create-workpackage-form--subject"
input-class="workpackage-subject"
:placeholder="t('integration_openproject', 'Work package subject')"
:class="{'subject-error': error}"
type="text"
@update:value="onSubjectChange" />
<p v-if="error.error && error.attribute === 'subject'" class="validation-error">
{{ error.message }}
</p>
<p v-else-if="error.error && error.multipleErrors.subject" class="validation-error multiple-error-subject">
{{ error.multipleErrors.subject }}
</p>
<div class="create-workpackage-form--type-status-container">
<div class="create-workpackage-form--type">
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Type *') }}
</div>
<NcSelect class="create-workpackage-form--select"
data-test-id="available-types"
input-id="createWorkPackageTypeInput"
:options="allowedTypes"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="type.label"
@option:selected="onSelectType">
<template #option="option">
{{ option.label }}
</template>
<template #no-options>
{{ t('integration_openproject', 'Please select a project') }}
</template>
</NcSelect>
<p v-if="customTypeError" class="validation-error type-error" v-html="sanitizedRequiredCustomTypeValidationErrorMessage" /> <!-- eslint-disable-line vue/no-v-html -->
<div>
<h2 class="create-workpackage-modal--title">
{{ t('integration_openproject', 'Create and link a new work package') }}
</h2>
<div class="create-workpackage-form-wrapper">
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Project *') }}
</div>
<div class="create-workpackage-form--status">
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Status *') }}
<NcSelect ref="createWorkPackageProjectInput"
class="create-workpackage-form--select"
input-id="createWorkPackageInput"
data-test-id="available-projects"
:placeholder="t('integration_openproject', 'Select a project')"
:options="mappedNodes"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="project.label"
:no-drop="noDropAvailableProjectDropDown"
@option:selected="onSelectProject">
<template #option="{ label, relation, counter }">
<span v-if="relation === 'child'" :style="{paddingLeft: counter + 'em' }" />
<span>{{ label }}</span>
</template>
<template #no-options>
{{ t('integration_openproject', 'Please link a project to this nextcloud storage') }}
</template>
</NcSelect>
<p v-if="error.error && error.attribute === 'project'" class="validation-error">
{{ error.message }}
</p>
<p v-else-if="error.error && error.multipleErrors.project" class="validation-error multiple-error-project">
{{ error.multipleErrors.project }}
</p>
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Subject *') }}
</div>
<NcInputField :value="subject"
class="create-workpackage-form--subject"
input-class="workpackage-subject"
:placeholder="t('integration_openproject', 'Work package subject')"
:class="{'subject-error': error}"
type="text"
@update:value="onSubjectChange" />
<p v-if="error.error && error.attribute === 'subject'" class="validation-error">
{{ error.message }}
</p>
<p v-else-if="error.error && error.multipleErrors.subject" class="validation-error multiple-error-subject">
{{ error.multipleErrors.subject }}
</p>
<div class="create-workpackage-form--type-status-container">
<div class="create-workpackage-form--type">
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Type *') }}
</div>
<NcSelect class="create-workpackage-form--select"
data-test-id="available-types"
input-id="createWorkPackageTypeInput"
:options="allowedTypes"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="type.label"
@option:selected="onSelectType">
<template #option="option">
{{ option.label }}
</template>
<template #no-options>
{{ t('integration_openproject', 'Please select a project') }}
</template>
</NcSelect>
<p v-if="customTypeError" class="validation-error type-error" v-html="sanitizedRequiredCustomTypeValidationErrorMessage" /> <!-- eslint-disable-line vue/no-v-html -->
</div>
<div class="create-workpackage-form--status">
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Status *') }}
</div>
<NcSelect class="create-workpackage-form--select"
data-test-id="available-statuses"
input-id="createWorkPackageStatusInput"
:options="allowedStatues"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="status.label"
@option:selected="onSelectStatus">
<template #option="option">
{{ option.label }}
</template>
<template #no-options>
{{ t('integration_openproject', 'Please select a project') }}
</template>
</NcSelect>
</div>
<NcSelect class="create-workpackage-form--select"
data-test-id="available-statuses"
input-id="createWorkPackageStatusInput"
:options="allowedStatues"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="status.label"
@option:selected="onSelectStatus">
<template #option="option">
{{ option.label }}
</template>
<template #no-options>
{{ t('integration_openproject', 'Please select a project') }}
</template>
</NcSelect>
</div>
</div>
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Assignee') }}
</div>
<NcSelect class="create-workpackage-form--select"
data-test-id="available-assignees"
input-id="createWorkPackageAssigneeInput"
:placeholder="t('integration_openproject', 'Select a user or group')"
:options="availableAssignees"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="assignee.label"
@option:selected="onSelectAssignee">
<template #option="option">
{{ option.label }}
</template>
<template #no-options>
{{ t('integration_openproject', 'Please select a project') }}
</template>
</NcSelect>
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Description') }}
</div>
<textarea v-model="description.raw" class="create-workpackage-form--description" :placeholder="t('integration_openproject', 'Work package description')" />
<div class="create-workpackage-form--button">
<NcButton class="create-workpackage-form--button--cancel" @click="closeModal">
{{ t("integration_openproject", "Cancel") }}
</NcButton>
<NcButton class="create-workpackage-form--button--create" :disabled="error.error || customTypeError" @click="createWorkpackage">
{{ t("integration_openproject", "Create") }}
</NcButton>
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Assignee') }}
</div>
<NcSelect class="create-workpackage-form--select"
data-test-id="available-assignees"
input-id="createWorkPackageAssigneeInput"
:placeholder="t('integration_openproject', 'Select a user or group')"
:options="availableAssignees"
:filterable="true"
:close-on-select="true"
:clear-search-on-blur="() => false"
:append-to-body="false"
:value="assignee.label"
@option:selected="onSelectAssignee">
<template #option="option">
{{ option.label }}
</template>
<template #no-options>
{{ t('integration_openproject', 'Please select a project') }}
</template>
</NcSelect>
<div class="create-workpackage-form--label">
{{ t('integration_openproject', 'Description') }}
</div>
<textarea v-model="description.raw" class="create-workpackage-form--description" :placeholder="t('integration_openproject', 'Work package description')" />
<div class="create-workpackage-form--button">
<NcButton class="create-workpackage-form--button--cancel" @click="closeModal">
{{ t("integration_openproject", "Cancel") }}
</NcButton>
<NcButton class="create-workpackage-form--button--create" :disabled="error.error || customTypeError" @click="createWorkpackage">
{{ t("integration_openproject", "Create") }}
</NcButton>
</div>
</div>
</div>
</NcModal>
Expand Down Expand Up @@ -224,6 +229,9 @@ export default {
description: DEFAULT_DESCRIPTION_VALUE,
error: DEFAULT_ERROR_VALUE,
customTypeError: false,
// when the modal opens the dropdown for selecting project gains focus automatically
// this is a workaround to prevent that by setting the dropdown to noDrop at the beginning
noDropAvailableProjectDropDown: true,
}),
computed: {
openModal() {
Expand Down Expand Up @@ -280,6 +288,13 @@ export default {
this.availableProjects.forEach(node => {
mapNode(node, 'parent')
})
// when the modal opens the dropdown for selecting project gains focus automatically
// this is a workaround to prevent that by bluring the focus and the enabling the dropDown that was
// disabled initially in data
if (this.$refs?.createWorkPackageProjectInput) {
document.getElementById(`${this.$refs?.createWorkPackageProjectInput?.inputId}`).blur()
this.noDropAvailableProjectDropDown = false
}
return mappedNodes
},
closeModal() {
Expand All @@ -299,6 +314,7 @@ export default {
this.projectId = null
this.error = DEFAULT_ERROR_VALUE
this.availableProjects = []
this.noDropAvailableProjectDropDown = true
},
async searchForProjects() {
const url = generateUrl('/apps/integration_openproject/projects')
Expand Down
1 change: 1 addition & 0 deletions src/views/ProjectsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<div class="projects"
:class="{'projects--empty': filterWorkpackagesByFileId.length === 0}">
<SearchInput v-if="!!isAdminConfigOk && !!isStateOk"
ref="hello"
:file-info="fileInfo"
:linked-work-packages="filterWorkpackagesByFileId"
:search-origin="searchOrigin"
Expand Down

0 comments on commit 1433dbb

Please sign in to comment.