Page MenuHomePhabricator

[Spike] Research OOUI Multi-Step form
Closed, ResolvedPublicSpike

Description

Background information

As a developer I want to explore the possibility of creating a multi-step form using OOUI and/or Codex.

Questions

  • What layout best suits a multi-step form in OOUI/Codex?

Continuing on from T334494 the StackLayout with Panels could be a layout that supports our proposed no-js strategy.

  • What are the steps required to build a multi-step form in OOUI/Codex?

Based on learnings in T329736 we can use the Codex card layout, with some modifications, to present a multi-step form. Each card could represent a step in the form and be hidden using the "v-if" condition until the card step is called. Here is an example below of the code that makes a card template hidden until called on a click event.

Each card has a "reason" value associated with it's click event so that the "reason" is stored as part of the final payload at form submission.

Sample Vue Template

<template>
<template>
	<div class="cdx-docs-card-group-with-thumbnails" v-if="activeStep == 1">
		<p>What do you need support with?</p>
		<cdx-card
			v-for="card in cards"
			:key="card.pageid"
			class="cdx-docs-card-group-with-thumbnails__card"
			:url="card.url"
			:force-thumbnail="false"
			:thumbnail="card.thumbnail"
			v-on:click="goToStep(2); addReason(1,card.title)"
		>
			<template #title>
				{{ card.title }}
			</template>
			<template #description>
				{{ card.description }}
			</template>
		</cdx-card>
	</div>
</template>
<template>
	<div class="cdx-docs-card-group-with-thumbnails" v-if="activeStep == 2">
		<p>{{reason_1}}</p>
		<hr/>
		<p>We’re very sorry to hear this. Our community does not tolerate harassment of any kind.
			Please share what type of harassment so that you can be supported appropriately.</p>
		<cdx-card
			v-for="card in cards2"
			:key="card.pageid"
			class="cdx-docs-card-group-with-thumbnails__card"
			:url="card.url"
			:force-thumbnail="false"
			:thumbnail="card.thumbnail"
			v-on:click="goToStep(3); addReason(2,card.title)"
		>
			<template #title>
				{{ card.title }}
			</template>
			<template #description>
				{{ card.description }}
			</template>

		</cdx-card>
	</div>
</template>
		<template id="step3" v-if="activeStep == 3">
			<h4>Summary Details: </h4>
			<strong>Need Support With: </strong> {{ reason_1 }}<br />
			<strong>Type of harassment: </strong> {{ reason_2 }}<br />
		</template>
</template>

<script>
const codex = require( '@wikimedia/codex' ),
	Vue = require( 'vue' );
const cards = [
	{
		pageid: 3613583,
		url: '#',
		title: 'Someone is harassing me',
		description: '',
		distance: '170m',
	},
	{
		pageid: 176931,
		url: '#',
		title: 'Someone is harassing someone else',
		description: '',
		distance: '300m'
	},
	{
		pageid: 11002203,
		url: '#',
		title: 'Someone is wikihounding me',
		description: '',
		distance: '350m'
	}
];

const cards2 = [
	{
		pageid: 3613583,
		url: '#',
		title: 'Sexual harassment',
		description: '',
		distance: '170m'
	},
	{
		pageid: 176931,
		url: '#',
		title: 'Hate Speech',
		description: '',
		distance: '300m'
	},
	{
		pageid: 11002203,
		url: '#',
		title: 'Threats or violence',
		description: '',
		distance: '350m'
	}
];


// @vue/component
module.exports = exports = Vue.defineComponent( {
	name: 'Pirs',
	components: {
		CdxCard: codex.CdxCard,
		CdxIcon: codex.CdxIcon,
	},
	data: function () {
		return {
			activeStep: 1,
				reason_1: '',
				reason_2:''
		}
	},
	setup() {
		return {
			cards,
			cards2
		}
	},

	methods: {
		goToStep: function(step) {
			this.activeStep = step;
		},
		addReason: function(step,reason) {
			switch (step) {
				case 1 :
					this.reason_1 = reason;
					break;
				case 2 :
					this.reason_2 = reason;
					break;

			}
		}
	}
} );
</script>
  • What files do we need to implement?

A vue template(s) and possibly a dataStore (Pinia)

Event Timeline

Took a stab at adding the cards/steps to extension.json in hopes of a more dynamic step configuration.

"config": {
		"PIRSConfig": {
			"value": {
				"default": {
					"ReceiverEmail": "pirs@wiki.zendesk.com"
				},
				"steps": {
					"step1": [
						{
							"pageid": 3613583,
							"url": "#",
							"title": "Someone is harassing me",
							"description": ""
						},
						{
							"pageid": 3613583,
							"url": "#",
							"title": "Someone is harassing someone else",
							"description": ""
						},
						{
							"pageid": 3613583,
							"url": "#",
							"title": "Someone is wikihounding me.",
							"description": ""
						}
					],
					"step2": [
						{
							"pageid": 3613583,
							"url": "#",
							"title": "Sexual Harassment",
							"description": ""
						},
						{
							"pageid": 3613583,
							"url": "#",
							"title": "Hate Speech",
							"description": ""
						},
						{
							"pageid": 3613583,
							"url": "#",
							"title": "Threats of Violence",
							"description": ""
						}
					]
				}
				}
			}
		},

@eigyan - the What files do we need to implement? item is unchecked, but I believe the Vue template code you have here is sufficient for the form to show up, with or without custom configuration options in the extension.json. Was there anything more you wanted to do here?

eigyan updated the task description. (Show Details)

@JKieserman you are correct, I forgot to check that box, but yes, essentially the vue files and maybe a dataStore is what we need.

Madalina subscribed.

Looks like we have what we needed.