mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-26 17:51:13 +08:00
Add wizard component [SCI-10035]
This commit is contained in:
parent
bd48ae1d07
commit
97c155f626
8 changed files with 268 additions and 1 deletions
56
app/javascript/packs/vue/design_system/modals.js
Normal file
56
app/javascript/packs/vue/design_system/modals.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { createApp } from 'vue/dist/vue.esm-bundler.js';
|
||||
import { shallowRef } from 'vue';
|
||||
|
||||
import WizardModal from '../../../vue/shared/wizard_modal.vue';
|
||||
import Step1 from './wizard_steps/step_1.vue';
|
||||
import Step2 from './wizard_steps/step_2.vue';
|
||||
import Step3 from './wizard_steps/step_3.vue';
|
||||
import { mountWithTurbolinks } from '../helpers/turbolinks.js';
|
||||
|
||||
const app = createApp({
|
||||
components: {
|
||||
Step1,
|
||||
Step2,
|
||||
Step3
|
||||
},
|
||||
methods: {
|
||||
fireAlert() {
|
||||
alert('Fired!');
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
wizardConfig: {
|
||||
title: 'Wizard steps',
|
||||
subtitle: 'Wizard subtitle description',
|
||||
steps: [
|
||||
{
|
||||
id: 'step1',
|
||||
icon: 'sn-icon sn-icon-open',
|
||||
label: 'Step 1',
|
||||
component: shallowRef(Step1)
|
||||
},
|
||||
{
|
||||
id: 'step2',
|
||||
icon: 'sn-icon sn-icon-edit',
|
||||
label: 'Step 2',
|
||||
component: shallowRef(Step2)
|
||||
},
|
||||
{
|
||||
id: 'step3',
|
||||
icon: 'sn-icon sn-icon-inventory',
|
||||
label: 'Step 3',
|
||||
component: shallowRef(Step3)
|
||||
}
|
||||
]
|
||||
},
|
||||
wizardParams: {
|
||||
text: 'Some text'
|
||||
},
|
||||
showWizard: false
|
||||
};
|
||||
}
|
||||
});
|
||||
app.component('WizardModal', WizardModal);
|
||||
app.config.globalProperties.i18n = window.I18n;
|
||||
mountWithTurbolinks(app, '#modals');
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<i class="sn-icon sn-icon-close"></i>
|
||||
</button>
|
||||
<h4 class="modal-title truncate flex items-center gap-4">
|
||||
Step 1 actions
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body grow">
|
||||
You can add any custom html here or render params like this:
|
||||
|
||||
{{ params }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-light" @click="$emit('close')">Cancel</button>
|
||||
<button class="btn btn-primary" @click="$emit('next')">Next</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
emits: ['close', 'next', 'back'],
|
||||
name: 'Step1',
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
wizardComponent: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<i class="sn-icon sn-icon-close"></i>
|
||||
</button>
|
||||
<h4 class="modal-title truncate flex items-center gap-4">
|
||||
Step 2 actions
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body grow">
|
||||
All steps have access to shared params
|
||||
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Type something"
|
||||
v-model="params.text"/>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-light" @click="$emit('back')">Back</button>
|
||||
<button class="btn btn-primary" @click="$emit('next')">Next</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
emits: ['back', 'next', 'close'],
|
||||
name: 'Step2',
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
wizardComponent: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<i class="sn-icon sn-icon-close"></i>
|
||||
</button>
|
||||
<h4 class="modal-title truncate flex items-center gap-4">
|
||||
Step 3 actions
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body grow">
|
||||
Our params - {{ params }}<br>
|
||||
|
||||
If you want emit action use wizardComponent
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<button class="btn btn-danger" @click="wizardComponent.$emit('alert')">Launch alert</button>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-light" @click="$emit('back')">Back</button>
|
||||
<button class="btn btn-primary" @click="$emit('close')">Apply</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
emits: ['back', 'close', 'alert', 'next'],
|
||||
name: 'Step3',
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
wizardComponent: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
73
app/javascript/vue/shared/wizard_modal.vue
Normal file
73
app/javascript/vue/shared/wizard_modal.vue
Normal file
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<div ref="modal" class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog !w-[900px]" role="document">
|
||||
<div class="modal-content !p-0 grid grid-cols-3">
|
||||
<div class="bg-sn-super-light-grey p-6 mb-1.5">
|
||||
<h3 class="mb-1.5">{{ config.title }}</h3>
|
||||
<div v-if="config.subtitle" class="text-sn-dark-grey">
|
||||
{{ config.subtitle }}
|
||||
</div>
|
||||
<div class="flex flex-col mt-4">
|
||||
<div v-for="(step, index) in config.steps" :key="step.id">
|
||||
<div v-if="index > 0"
|
||||
class="ml-0.5 left-4 relative h-8 w-0 border border-r-0 border-solid"
|
||||
:class="{
|
||||
'!border-sn-dark-grey': index <= activeStep,
|
||||
'!border-sn-sleepy-grey': index > activeStep
|
||||
}"
|
||||
></div>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="rounded bg-white border border-sn-sleepy-grey p-1.5">
|
||||
<i :class="step.icon"></i>
|
||||
</div>
|
||||
<span
|
||||
class="font-bold text-xs"
|
||||
:class="{
|
||||
'text-sn-dark-grey': index <= activeStep,
|
||||
'text-sn-grey': index > activeStep
|
||||
}"
|
||||
>
|
||||
{{ step.label }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-2 p-6 flex flex-col">
|
||||
<component
|
||||
:is="config.steps[activeStep].component"
|
||||
:params="params"
|
||||
:wizardComponent="this"
|
||||
@close="close"
|
||||
@back="activeStep -= 1"
|
||||
@next="activeStep += 1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modalMixin from './modal_mixin';
|
||||
|
||||
export default {
|
||||
name: 'WizardModal',
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
mixins: [modalMixin],
|
||||
data() {
|
||||
return {
|
||||
activeStep: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
16
app/views/design_elements/_modals.html.erb
Normal file
16
app/views/design_elements/_modals.html.erb
Normal file
|
@ -0,0 +1,16 @@
|
|||
<div>
|
||||
<h1>Modals</h1>
|
||||
<div id="modals" class="flex items-center gap-4 flex-wrap mt-6">
|
||||
<button @click="showWizard = true" class="btn btn-primary">Show Wizard Modal</button>
|
||||
<wizard-modal
|
||||
v-if="showWizard"
|
||||
@close="showWizard = false"
|
||||
@alert="fireAlert"
|
||||
:params="wizardParams"
|
||||
:config="wizardConfig"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<%= javascript_include_tag 'vue_design_system_modals' %>
|
|
@ -0,0 +1 @@
|
|||
<%= render partial: 'modals' %>
|
|
@ -49,7 +49,8 @@ const entryList = {
|
|||
vue_components_manage_stock_value_modal: './app/javascript/packs/vue/manage_stock_value_modal.js',
|
||||
vue_legacy_datetime_picker: './app/javascript/packs/vue/legacy/datetime_picker.js',
|
||||
vue_open_locally_menu: './app/javascript/packs/vue/open_locally_menu.js',
|
||||
vue_scinote_edit_download: './app/javascript/packs/vue/scinote_edit_download.js'
|
||||
vue_scinote_edit_download: './app/javascript/packs/vue/scinote_edit_download.js',
|
||||
vue_design_system_modals: './app/javascript/packs/vue/design_system/modals.js'
|
||||
}
|
||||
|
||||
// Engine pack loading based on https://github.com/rails/webpacker/issues/348#issuecomment-635480949
|
||||
|
|
Loading…
Reference in a new issue