-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
prototype for input forum validation
- Loading branch information
Showing
10 changed files
with
1,189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Forum Validation Prototype Implementation | ||
|
||
This README provides instructions on how to incorporate files related to a forum validation implementation into the main | ||
project. | ||
|
||
## File Structure | ||
|
||
The files are organized in the following way: | ||
|
||
- Frontend JavaScript and Vue components and their corresponding test files | ||
- End-to-end system test files | ||
|
||
## Instructions | ||
|
||
1. **Frontend** | ||
- `inputDialog.js` should be placed directly under your project's `frontend/src` directory. | ||
|
||
- The Vue components `InputDialog.vue`, `InputDialogAttachUrl.vue`, and `InputDialogUploadFile.vue` should be placed | ||
inside the directory `src/components/Dialogs/` under your project's `frontend` directory. The path should look | ||
like: `frontend/src/components/Dialogs/`. | ||
|
||
- Test files for these components `InputDialog.spec.js`, `InputDialogAttachUrl.spec.js`, | ||
`InputDialogUploadFile.spec.js` should be placed in `test/components/Dialogs/` under your project's `frontend` | ||
directory. The path should look like: `frontend/test/components/Dialogs/`. | ||
|
||
2. **System-tests** | ||
- End-to-end test files `case_supporting_evidence.cy.js` and `import_new_case.cy.js` should be placed inside the | ||
`e2e` directory under the `system-tests` directory in your main project. | ||
The path should look like: `system-tests/e2e/`. | ||
|
||
3. **Testing** | ||
- To test the frontend components, run `yarn test:unit` in your main project's `frontend` directory. | ||
- To test the end-to-end system tests, first make sure the application is running locally. Then, run `yarn test:e2e` | ||
in your main project's `system-tests` directory. | ||
|
||
Please ensure you maintain this directory structure for the application to function correctly. | ||
|
||
## Notes | ||
|
||
- After adding these files, you might need to rebuild the docker containers based on your development environment. | ||
- Make sure to run all the tests to ensure the integration went smoothly. |
148 changes: 148 additions & 0 deletions
148
docs/prototypes/forum-valadation/frontend/src/components/Dialogs/InputDialog.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
<template> | ||
<div v-if="dialog.state.active" class="modal-background"> | ||
<div :class="['modal-container', dialog.state.message ? 'limit-width' : '']"> | ||
<div class="tab-header"> | ||
<button | ||
v-for="(tab, index) in dialog.state.tabs" | ||
:key="`button-${tab.name}-${index}`" | ||
:class="tab.name == dialog.state.activeTabName ? 'tab-button-active' : ''" | ||
class="tab-button" | ||
@click="dialog.state.activeTabName = tab.name" | ||
:data-test="`button-${tab.name}`" | ||
> | ||
<img | ||
v-if="tab.icon == 'phenotips'" | ||
src="@/assets/phenotips-favicon-96x96.png" | ||
/> | ||
<font-awesome-icon v-else | ||
:icon="'file' == tab.icon ? ['far', 'file'] : tab.icon" | ||
size="2xl"> | ||
</font-awesome-icon> | ||
</button> | ||
</div> | ||
<div v-if="dialog.state.message" | ||
class="warning-message" | ||
v-html="dialog.state.message" | ||
data-test="warning-message"> | ||
</div> | ||
<component v-bind:is="dialog.state.activeTabName" | ||
:userInput = "dialog.activeTab().input" | ||
v-bind="dialog.activeTab().props" | ||
:runValidation="shouldRunValidation" | ||
@update:userInput="dialog.updateActiveTabInput" | ||
@update:allRequiredFieldsFilled="allRequiredFieldsFilled = $event" | ||
@validationDone="shouldRunValidation = false" | ||
/> | ||
<div class="button-row"> | ||
<button class="secondary-button" @click="dialog.cancel()" data-test="cancel"> | ||
{{ dialog.state.cancelText }} | ||
</button> | ||
<button class="secondary-button" v-if="dialog.state.deleteText!=''" @click="dialog.delete()" data-test="delete"> | ||
{{ dialog.state.deleteText }} | ||
</button> | ||
<button class="primary-button" | ||
@click="confirmClicked()" | ||
data-test="confirm"> | ||
{{ dialog.state.confirmText }} | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import InputDialogAttachUrl from '@/components/Dialogs/InputDialogAttachUrl.vue'; | ||
import InputDialogUploadFile from '@/components/Dialogs/InputDialogUploadFile.vue'; | ||
import dialog from '@/inputDialog.js'; | ||
export default { | ||
name: 'input-dialog', | ||
components: { | ||
InputDialogAttachUrl, | ||
InputDialogUploadFile, | ||
}, | ||
data: function() { | ||
return { | ||
dialog, | ||
allRequiredFieldsFilled: false, | ||
shouldRunValidation: false, | ||
}; | ||
}, | ||
methods: { | ||
confirmClicked() { | ||
if (!this.allRequiredFieldsFilled) { | ||
this.shouldRunValidation = true; | ||
this.$nextTick(() => { | ||
if (this.allRequiredFieldsFilled) { | ||
this.dialog.confirmation(this.dialog.activeTab().input); | ||
this.allRequiredFieldsFilled = false; | ||
} | ||
}); | ||
} else { | ||
this.dialog.confirmation(this.dialog.activeTab().input); | ||
this.allRequiredFieldsFilled = false; | ||
} | ||
}, | ||
}, | ||
}; | ||
</script> | ||
|
||
<style scoped> | ||
.modal-container { | ||
padding: var(--p-16); | ||
display: flex; | ||
flex-direction: column; | ||
min-width: 25rem; | ||
min-height: auto; | ||
gap: var(--p-16); | ||
align-items: stretch; | ||
} | ||
.tab-header { | ||
margin: auto; | ||
border: 2px var(--rosalution-grey-100) solid; | ||
border-radius: var(--input-border-radius); | ||
width: 160px; | ||
display: flex; | ||
justify-content: center; | ||
} | ||
.tab-button { | ||
width: 2.5rem; | ||
background-color: var(--rosalution-white); | ||
border: none; | ||
padding-top: var(--p-10); | ||
padding-bottom: var(--p-10); | ||
} | ||
.tab-header .tab-button:not(:first-child) { | ||
border-left: 2px var(--rosalution-grey-100) solid; | ||
padding-left: var(--p-8); | ||
} | ||
.tab-button-active { | ||
color: var(--rosalution-blue-200) !important; | ||
} | ||
.button-row { | ||
display: flex; | ||
justify-content: flex-end; | ||
align-items: center; | ||
gap: var(--p-16); | ||
} | ||
.warning-message{ | ||
font-size: var(--font-size-16); | ||
font-weight: var(--font-weight-regular); | ||
line-height: var(--line-height-24); | ||
text-align: center; | ||
} | ||
.limit-width { | ||
max-width: 25rem; | ||
} | ||
</style> |
113 changes: 113 additions & 0 deletions
113
docs/prototypes/forum-valadation/frontend/src/components/Dialogs/InputDialogAttachUrl.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<template> | ||
<input v-if="'name' in userInput" placeholder="Text to display (required)" v-model="name" data-test="name-input" | ||
:class="{ 'invalid-input-highlight': highlight && !name }" /> | ||
<div v-if="'name' in userInput && highlight && !name" class="required-message" data-test="required"> | ||
*required | ||
</div> | ||
<input placeholder="Paste a link (required)" v-model="url" data-test="link-input" | ||
:class="{ 'invalid-input-highlight': highlight && !url }" /> | ||
<div v-if="highlight && !url" class="required-message" data-test="required"> | ||
*required | ||
</div> | ||
<textarea v-if="'comments' in userInput" class="comments" placeholder="Comments" v-model="comments" | ||
data-test="comments-text-area"> | ||
</textarea> | ||
</template> | ||
|
||
|
||
<script> | ||
export default { | ||
name: 'input-dialog-attach-url', | ||
emits: ['update:userInput', 'update:allRequiredFieldsFilled', 'validationDone'], | ||
props: { | ||
userInput: { | ||
type: Object, | ||
required: true, | ||
}, | ||
runValidation: { | ||
type: Boolean, | ||
}, | ||
}, | ||
data() { | ||
return { | ||
highlight: false, | ||
}; | ||
}, | ||
computed: { | ||
requiredFields() { | ||
return this.userInput.requiredFields || []; | ||
}, | ||
name: { | ||
get() { | ||
return this.userInput.name; | ||
}, | ||
set(value) { | ||
this.updateUserInput('name', value); | ||
}, | ||
}, | ||
url: { | ||
get() { | ||
return this.userInput.data; | ||
}, | ||
set(value) { | ||
this.updateUserInput('data', value); | ||
}, | ||
}, | ||
comments: { | ||
get() { | ||
return this.userInput['comments']; | ||
}, | ||
set(value) { | ||
this.updateUserInput('comments', value); | ||
}, | ||
}, | ||
allRequiredFieldsFilled() { | ||
return this.requiredFields.every((field) => !!this[field] && this[field].length > 0); | ||
}, | ||
}, | ||
watch: { | ||
runValidation(currentValidationState, previousValidationState) { | ||
if (currentValidationState !== previousValidationState && currentValidationState === true) { | ||
this.validateRequiredFields(); | ||
this.$emit('validationDone'); | ||
} | ||
}, | ||
}, | ||
methods: { | ||
confirmClicked() { | ||
this.validateRequiredFields(); | ||
}, | ||
updateUserInput(field, value) { | ||
const input = this.userInput; | ||
input[field] = value; | ||
this.$emit('update:userInput', input); | ||
}, | ||
validateRequiredFields() { | ||
const allFieldsFilled = this.requiredFields.every((field) => !!this[field] && this[field].length > 0); | ||
if (!allFieldsFilled) { | ||
this.highlightRequiredFields(); | ||
} else { | ||
this.$emit('update:allRequiredFieldsFilled', allFieldsFilled); | ||
} | ||
}, | ||
highlightRequiredFields() { | ||
this.highlight = true; | ||
}, | ||
}, | ||
}; | ||
</script> | ||
|
||
|
||
<style> | ||
.comments { | ||
flex: 3 0 auto; | ||
height: 8rem; | ||
} | ||
.required-message { | ||
color: var(--rosalution-red-100); | ||
transform: translateY(-1rem); | ||
} | ||
</style> |
Oops, something went wrong.