Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue Route in demo App #183

Merged
merged 11 commits into from
Sep 11, 2024
Merged
18 changes: 16 additions & 2 deletions packages/web-forms/e2e/vue.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { faker } from '@faker-js/faker';
import { expect, test } from '@playwright/test';
import { expect, Page, test } from '@playwright/test';

const expandAllCategories = async (page: Page) => {
await page.evaluate(() => {
const collapsedDetails = document.querySelectorAll<HTMLDetailsElement>('details:not([open])');

collapsedDetails.forEach((details) => {
details.open = true;
});
});
};

test('All forms are rendered and there is no console error', async ({ page, browserName }) => {
let consoleErrors = 0;
Expand All @@ -15,7 +25,10 @@ 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.locator('ul.form-list li').all();
// Let's expand all categories, so that Form list is visible
await expandAllCategories(page);

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

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

Expand Down Expand Up @@ -81,6 +94,7 @@ test('All forms are rendered and there is no console error', async ({ page, brow
}

await page.goBack();
await expandAllCategories(page);
}

expect(consoleErrors).toBe(0);
Expand Down
2 changes: 1 addition & 1 deletion packages/web-forms/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/demo.ts"></script>
<script type="module" src="/src/demo/demo.ts"></script>
</body>
</html>
3 changes: 2 additions & 1 deletion packages/web-forms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@
"vite": "^5.4.3",
"vite-plugin-css-injected-by-js": "^3.5.1",
"vitest": "^2.0.5",
"vue": "3.3.4"
"vue": "3.3.4",
"vue-router": "^4.4.3"
},
"peerDependencies": {
"vue": "^3.3.4"
Expand Down
90 changes: 0 additions & 90 deletions packages/web-forms/src/OdkWebFormDemo.vue

This file was deleted.

4 changes: 2 additions & 2 deletions packages/web-forms/src/components/OdkWebForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ const formErrorMessage = computed(() => {

watchEffect(() => {
if(submitPressed.value && formErrorMessage.value) {
(errorMessagePopover.value?.$el as HTMLElement)?.showPopover();
(errorMessagePopover.value?.$el as HTMLElement)?.showPopover?.();
}
else{
(errorMessagePopover.value?.$el as HTMLElement)?.hidePopover();
(errorMessagePopover.value?.$el as HTMLElement)?.hidePopover?.();
}
})
</script>
Expand Down
109 changes: 109 additions & 0 deletions packages/web-forms/src/demo/FormList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<script lang="ts" setup>
import { RouterLink } from 'vue-router';

const formFixtureGlobImports = import.meta.glob<true, 'raw', string>('../../../ui-solid/fixtures/xforms/**/*.xml', {
query: '?raw'
});

type CategoryType = Record<string, string[]>;

const categories = Object.keys(formFixtureGlobImports)
.map(f => f.replace('../../../ui-solid/fixtures/xforms/', ''))
.reduce((result: CategoryType, f:string) => {
// TODO! These would normally be inferred as `string | undefined`, but the
// current TypeScript configuration is overly lax. See
// https://github.com/getodk/web-forms/issues/212
const [categoryName, formName] = f.split('/');

result[categoryName] ??= [];
result[categoryName].push(formName)

return result;
}, {});
</script>

<template>
<div class="component-root">
<h1>Demo Forms</h1>
<ul class="category-list">
<li
v-for="(category,categoryName) in categories"
:key="categoryName"
>
<details>
<summary>{{ categoryName }}</summary>

<ul class="form-list">
<li v-for="formName in category" :key="formName">
<RouterLink :to="`/form/${categoryName}/${formName}`">
{{ formName }}
</RouterLink>
</li>
</ul>
</details>
</li>
</ul>
</div>
</template>

<style scoped>
.component-root {
background: white;
height: 100vh;
margin-top: -25px;
}

h1 {
margin-left: 10px;
padding-top: 20px;
}

.category-list {
padding: 0;

> li {
list-style: none;
cursor: pointer;
margin: 10px;
font-size: 20px;

summary {
padding: 0.5rem;

&:hover {
background-color: var(--gray-100);
}
}

ul.form-list {
padding: 0 0 0 20px;

li {
list-style: none;
margin: 10px;
border: 1px solid var(--primary-500);
border-radius: 10px;
cursor: pointer;
background-color: var(--surface-0);
font-size: 16px;

a {
display: block;
padding: 10px;
text-decoration: none;
color: var(--gray-900);

&:visited {
color: var(--gray-900)
}
}
}

li:hover {
background-color: var(--primary-50);
}
}
}
}

</style>
42 changes: 42 additions & 0 deletions packages/web-forms/src/demo/FormPreview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import OdkWebForm from '../components/OdkWebForm.vue';

const route = useRoute()

const formFixtureGlobImports = import.meta.glob<false, 'raw', string>('../../../ui-solid/fixtures/xforms/**/*.xml', {
query: '?raw',
import: 'default',
eager: false,
});

const categoryParam = route.params.category as string;
const formParam = route.params.form as string;
const formPath = `../../../ui-solid/fixtures/xforms/${categoryParam}/${formParam}`;

const formXML = ref<string>();

formFixtureGlobImports[formPath]()
.then((xml:string) => {
formXML.value = xml;
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error('Failed to load the Form XML', error);

alert('Failed to load the Form XML');
});

const handleSubmit = () => {
alert(`Submit button was pressed`);
}

</script>

<template>
<OdkWebForm v-if="formXML" :form-xml="formXML" @submit="handleSubmit" />
<div v-else>
Loading...
</div>
</template>
7 changes: 7 additions & 0 deletions packages/web-forms/src/demo/OdkWebFormDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script setup lang="ts">
import { RouterView } from 'vue-router';
</script>

<template>
<RouterView />
</template>
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import type { Component } from 'vue';
import { createApp } from 'vue';

import { webFormsPlugin } from '../WebFormsPlugin';
import OdkWebFormDemo from './OdkWebFormDemo.vue';
import { webFormsPlugin } from './WebFormsPlugin';

import roboto from '@fontsource/roboto/300.css?inline';
import icomoon from './assets/css/icomoon.css?inline';
import theme from './themes/2024-light/theme.scss?inline';
import icomoon from '../assets/css/icomoon.css?inline';
import theme from '../themes/2024-light/theme.scss?inline';
// TODO/sk: Purge it - postcss-purgecss
import primeflex from 'primeflex/primeflex.css?inline';

import demoStyles from './assets/css/style.scss?inline';
import demoStyles from '../assets/css/style.scss?inline';
import router from './router';

const styles = [roboto, icomoon, theme, primeflex, demoStyles].join('\n\n');
const stylesheet = new CSSStyleSheet();
Expand All @@ -21,4 +22,5 @@ document.adoptedStyleSheets.push(stylesheet);

const app = createApp(OdkWebFormDemo as Component);
app.use(webFormsPlugin);
app.use(router);
app.mount('#app');
16 changes: 16 additions & 0 deletions packages/web-forms/src/demo/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Component } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router';
import FormList from './FormList.vue';
import FormPreview from './FormPreview.vue';

const routes = [
{ path: '/', component: FormList as Component },
{ path: '/form/:category/:form', component: FormPreview as Component },
];

const router = createRouter({
history: createWebHashHistory(),
routes,
});

export default router;
2 changes: 1 addition & 1 deletion packages/web-forms/tests/components/FormQuestion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const mountComponent = async (formPath: string, questionNumber: number) => {

describe('FormQuestion', () => {
it('shows InputText control for string nodes', async () => {
const component = await mountComponent('minimal.xform.xml', 0);
const component = await mountComponent('other/minimal.xform.xml', 0);

const inputText = component.findComponent(InputText);

Expand Down
3 changes: 3 additions & 0 deletions packages/web-forms/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,7 @@ export default defineConfig({
],
},
},
optimizeDeps: {
force: true,
},
});
Loading
Loading