Skip to content

Commit

Permalink
Refactoring:
Browse files Browse the repository at this point in the history
* Declared different colors as variables.
* Removed show/back buttons from demo, added navigation via history API
* Made FormLanguageDialog and FormLanguageMenu dumb components, state change is handled by parent
  • Loading branch information
sadiqkhoja committed Jun 21, 2024
1 parent 2ce20de commit 73439d6
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 79 deletions.
4 changes: 2 additions & 2 deletions packages/web-forms/e2e/vue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test('All forms are rendered and there is no console error', async ({ page, brow
// this ensures that Vue application is loaded before proceeding forward.
await expect(page.getByText('Demo Forms')).toBeVisible();

const forms = await page.getByText('Show').all();
const forms = await page.locator('ul.form-list li').all();

expect(forms.length).toBeGreaterThan(0);

Expand Down Expand Up @@ -80,7 +80,7 @@ test('All forms are rendered and there is no console error', async ({ page, brow
await page.locator('.language-dd-label').last().click();
}

await page.getByText('Back').click();
await page.goBack();
}

expect(consoleErrors).toBe(0);
Expand Down
57 changes: 49 additions & 8 deletions packages/web-forms/src/OdkWebFormDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,66 @@ const handleSubmit = () => {
alert(`Submit button was pressed`);
}
const showForm = (form: [string, string]) => {
selectForm.value = form;
history.pushState({form: form }, "", "/" + form[0]);
}
interface PopStateEventWithForm extends PopStateEvent {
state: {form: [string, string]};
}
window.addEventListener("popstate", (event:PopStateEventWithForm) => {
if(!event.state) {
selectForm.value = null;
}
else {
selectForm.value = event.state.form;
}
});
if(location.pathname != '/'){
const demoForm = demoForms.find(f => `/${f[0]}` === location.pathname) ?? null;
if(demoForm) {
selectForm.value = demoForm;
}
else{
history.replaceState(null, "", "/");
}
}
</script>

<template>
<div v-if="!selectForm">
<h1>Demo Forms</h1>
<ul>
<li v-for="form in demoForms" :key="form[0]">
<ul class="form-list">
<li v-for="form in demoForms" :key="form[0]" @click="showForm(form)">
{{ form[0] }}
<button @click="selectForm = form">
Show
</button>
</li>
</ul>
</div>
<div v-else>
<button @click="selectForm = null">
Back
</button>
<OdkWebForm v-if="selectForm" :form-xml="selectForm[1]" @submit="handleSubmit" />
</div>
</template>

<style>
ul.form-list {
padding: 0;
li {
list-style: none;
padding: 10px;
margin: 10px;
border: 1px solid var(--primary-500);
border-radius: 10px;
cursor: pointer;
background-color: var(--surface-0);
}
li:hover {
background-color: var(--primary-50);
}
}
</style>
80 changes: 49 additions & 31 deletions packages/web-forms/src/components/FormHeader.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { type RootNode } from '@getodk/xforms-engine';
import { type FormLanguage, type RootNode, type SyntheticDefaultLanguage } from '@getodk/xforms-engine';
import PrimeButton from 'primevue/button';
import PrimeCard from 'primevue/card';
import PrimeMenu from 'primevue/menu';
Expand All @@ -10,7 +10,12 @@ import FormLanguageMenu from './FormLanguageMenu.vue';
const props = defineProps<{form: RootNode}>();
const languageDialogState = ref(false);
const menu = ref<PrimeMenu>();
const languages = props.form.languages.filter(language => !language.isSyntheticDefault);
const isFormLanguage = (lang: FormLanguage | SyntheticDefaultLanguage) : lang is FormLanguage => {
return !lang.isSyntheticDefault;
}
const languages = props.form.languages.filter(isFormLanguage);
const print = () => window.print();
Expand All @@ -29,13 +34,21 @@ if(languages.length > 0){
command: () => languageDialogState.value = true
})
}
const handleLanguageChange = (event: FormLanguage) => {
props.form.setLanguage(event);
};
</script>

<template>
<!-- for desktop -->
<div class="hidden lg:flex justify-content-end flex-wrap gap-3 larger-screens">
<PrimeButton class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<FormLanguageMenu :form="form" />
<FormLanguageMenu
:active-language="form.currentState.activeLanguage"
:languages="languages"
@update:active-language="handleLanguageChange"
/>
</div>
<PrimeCard class="form-title hidden lg:block">
<template #content>
Expand All @@ -46,25 +59,32 @@ if(languages.length > 0){
</PrimeCard>

<!-- for mobile and tablet -->
<div class="lg:hidden smaller-screens">
<div class="flex align-items-center">
<h1 class="flex-grow-1">
{{ form.definition.bind.form.title }}
</h1>

<!-- for tablet -->
<div class="odk-menu-bar hidden md:flex justify-content-end gap-3">
<PrimeButton class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<FormLanguageMenu :form="form" />
</div>
<div class="flex lg:hidden align-items-center smaller-screens">
<h1 class="flex-grow-1">
{{ form.definition.bind.form.title }}
</h1>

<!-- for tablet -->
<div class="form-options hidden md:flex justify-content-end gap-3">
<PrimeButton class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<FormLanguageMenu
:active-language="form.currentState.activeLanguage"
:languages="languages"
@update:active-language="handleLanguageChange"
/>
</div>

<!-- for mobile -->
<div class="odk-menu-bar flex md:hidden justify-content-end gap-3">
<PrimeButton v-if="languages.length > 0" icon="icon-menu" class="btn-menu" text rounded aria-label="Menu" @click="menu?.toggle" />
<PrimeButton v-else class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<PrimeMenu id="overlay_menu" ref="menu" :model="items" :popup="true" />
<FormLanguageDialog v-model:state="languageDialogState" :form="form" />
</div>
<!-- for mobile -->
<div class="form-options flex md:hidden">
<PrimeButton v-if="languages.length > 0" icon="icon-menu" class="btn-menu" text rounded aria-label="Menu" @click="menu?.toggle" />
<PrimeButton v-else class="print-button" severity="secondary" rounded icon="icon-local_printshop" @click="print" />
<PrimeMenu id="overlay_menu" ref="menu" :model="items" :popup="true" />
<FormLanguageDialog
v-model:state="languageDialogState"
:active-language="form.currentState.activeLanguage"
:languages="languages"
@update:active-language="handleLanguageChange"
/>
</div>
</div>
</template>
Expand All @@ -84,9 +104,12 @@ if(languages.length > 0){
}
}
.form-title {
// var(--light-elevation-1);
border-radius: 10px;
box-shadow: 0px 1px 3px 1px #00000026;
box-shadow: var(--light-elevation-1);
border-top: none;
margin-top: 20px;
Expand All @@ -102,25 +125,20 @@ if(languages.length > 0){
}
.smaller-screens {
// this adds border to parent div so that bottom shadow of immediate child
// is visible.
border-bottom: 3px solid #fff;
> div {
box-shadow: 0px 1px 2px 0px #0000004D;
}
background-color: var(--surface-0);
filter: drop-shadow(0px 2px 6px rgba(0, 0, 0, 0.15)) drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.30)) ;
h1 {
padding-left: 10px;
font-size: 1.5rem;
}
.odk-menu-bar{
.form-options{
padding-right: 10px;
}
.btn-menu{
color: #000;
color: var(--surface-900);
}
}
Expand Down
23 changes: 6 additions & 17 deletions packages/web-forms/src/components/FormLanguageDialog.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
<script setup lang="ts">
import type { FormLanguage, RootNode } from '@getodk/xforms-engine';
import type { ActiveLanguage, FormLanguage } from '@getodk/xforms-engine';
import PrimeButton from 'primevue/button';
import PrimeDialog from 'primevue/dialog';
import PrimeRadioButton from 'primevue/radiobutton';
import { ref } from 'vue';
const props = defineProps<{ form: RootNode, state: boolean }>();
const emit = defineEmits(['update:state']);
const props = defineProps<{ state: boolean, languages: FormLanguage[], activeLanguage: ActiveLanguage }>();
const emit = defineEmits(['update:state', 'update:activeLanguage']);
const languages = props.form.languages.filter(language => !language.isSyntheticDefault);
const selectedLanguage = ref<FormLanguage>();
const initSelectedLanguage = () => {
if(!props.form.currentState.activeLanguage.isSyntheticDefault) {
selectedLanguage.value = props.form.currentState.activeLanguage;
}
}
initSelectedLanguage();
const selectedLanguage = ref<ActiveLanguage>(props.activeLanguage);
const handleSave = () => {
if(!selectedLanguage.value?.isSyntheticDefault){
props.form.setLanguage(selectedLanguage.value!);
}
emit('update:activeLanguage', selectedLanguage.value);
emit('update:state',false);
};
const handleCancel = () => {
initSelectedLanguage();
selectedLanguage.value = props.activeLanguage;
emit('update:state',false);
}
Expand Down
29 changes: 15 additions & 14 deletions packages/web-forms/src/components/FormLanguageMenu.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
<script setup lang="ts">
import type { FormLanguage, RootNode } from '@getodk/xforms-engine';
import Dropdown, { type DropdownChangeEvent } from 'primevue/dropdown';
import type { ActiveLanguage, FormLanguage } from '@getodk/xforms-engine';
import Dropdown from 'primevue/dropdown';
const props = defineProps<{ form: RootNode }>();
defineProps<{ languages: FormLanguage[], activeLanguage: ActiveLanguage }>();
const languages = props.form.languages.filter(language => !language.isSyntheticDefault);
interface LanguageDropdownChangeEvent extends DropdownChangeEvent {
readonly value: FormLanguage;
}
const handleLanguageChange = (event: LanguageDropdownChangeEvent) => {
props.form.setLanguage(event.value);
};
defineEmits(['update:activeLanguage'])
</script>

<template>
<Dropdown
v-if="languages.length > 0"
:model-value="form.currentState.activeLanguage"
:model-value="activeLanguage"
:options="languages"
option-label="language"
class="flex align-items-center rounded with-icon language-changer"
aria-label="change language"
@change="handleLanguageChange"
@update:model-value="$emit('update:activeLanguage', $event)"
>
<template #value="slotProps">
<span class="icon-language" />
Expand Down Expand Up @@ -61,4 +53,13 @@ const handleLanguageChange = (event: LanguageDropdownChangeEvent) => {
font-size: 1.5rem;
}
}
</style>

<style>
@media print {
.p-menu {
display: none;
}
}
</style>
8 changes: 4 additions & 4 deletions packages/web-forms/src/components/OdkWebForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ initializeForm(props.formXml, {
},
}).then((f) => {
odkForm.value = f;
// TODO/sk: remove once dust settles
// eslint-disable-next-line -- temporary code
console.log((f as any).childrenState.getChildren());
}).catch(() => {}); // eslint-disable-line -- noop
const handleSubmit = () => {
Expand Down Expand Up @@ -59,6 +56,7 @@ const handleSubmit = () => {
.odk-form {
width: 100%;
color: var(--text-color);
.form-wrapper {
max-width: 900px;
Expand All @@ -68,7 +66,7 @@ const handleSubmit = () => {
.questions-card {
border-radius: 10px;
box-shadow: 0px 1px 3px 1px #00000026;
box-shadow: var(--light-elevation-1);
border-top: none;
margin-top: 20px;
Expand Down Expand Up @@ -98,6 +96,8 @@ const handleSubmit = () => {
.odk-form {
.form-wrapper {
max-width: unset;
padding-top: unset;
.questions-card {
border-radius: unset;
box-shadow: unset;
Expand Down
18 changes: 15 additions & 3 deletions packages/web-forms/src/themes/2024-light/theme.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
$primaryColor: #3e9fcc;
// As called by Designer
$odkBlue: #3e9fcc;
$lightBlue: #e9f8ff;
$lightGray: #cbcacc;
$textColour: #1b1b1f;
$hintText: #6d6d6d;
$errorText: #b3261e;
$errorLight: #ffedea;

// Override theme colors
$primaryColor: $odkBlue;
$primaryTextColor: #ffffff;
$accentColor: #ffffff;
$accentTextColor: #424242;

$primary50: #d8ecf5;
$primary50: $lightBlue;
$emphasis-high: $textColour;

@import 'primevue-sass-theme/themes/material/material-light/standard/indigo/theme.scss';

Expand All @@ -12,4 +22,6 @@ $primary50: #d8ecf5;

:root {
--primary-50: #{$primary50};
--text-color: #{$textColour};
--light-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, 0.3), 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
}

0 comments on commit 73439d6

Please sign in to comment.