cattr-app/frontend-application

View on GitHub
app/core/views/Setup.vue

Summary

Maintainability
Test Coverage
<template>
    <div class="content-wrapper">
        <div class="container">
            <div class="at-container crud__content">
                <div class="wrap-steps">
                    <at-steps ref="steps" :current="currentStep" class="wrap-steps__steps">
                        <at-step
                            v-for="(component, index) in components"
                            :key="index"
                            :status="getStatus(component.status)"
                            :title="$t('reset.step', { n: ++index })"
                            :description="$t(`setup.step_description.${component.name}`)"
                        />
                    </at-steps>
                </div>

                <div class="col form-wrap">
                    <div class="form-wrap__header">
                        <div class="header-text">
                            <h2 class="header-text__title">
                                {{ $t(`setup.header.${this.components[this.currentStep].name}.title`) }}
                            </h2>
                            <p class="header-text__subtitle">
                                {{ $t(`setup.header.${this.components[this.currentStep].name}.subtitle`) }}
                            </p>
                        </div>
                    </div>
                    <div class="form-wrap__component">
                        <component
                            :is="components[currentStep].component"
                            :storage="components[currentStep].storage"
                            @setStatus="$set(components[currentStep], 'status', $event)"
                            @updateStorage="$set(components[currentStep], 'storage', $event)"
                        />
                    </div>
                </div>

                <div class="wrap-buttons" :style="currentStep === 0 ? 'justify-content: flex-end' : ''">
                    <at-button
                        v-if="currentStep !== 0"
                        type="primary"
                        class="wrap-buttons__button"
                        @click="changeStep(-1)"
                    >
                        {{ $t('setup.buttons.back') }}
                    </at-button>
                    <at-button
                        v-if="currentStep !== components.length - 1"
                        type="primary"
                        class="wrap-buttons__button"
                        :disabled="isNextStepDisabled"
                        @click="changeStep(1)"
                    >
                        {{ $t('setup.buttons.next') }}
                    </at-button>
                    <at-button v-else type="success" :disabled="isNextStepDisabled" @click="completeSetup">
                        {{ $t('setup.buttons.complete') }}
                    </at-button>
                </div>
            </div>
        </div>
        <at-modal
            v-model="installationIsInProgress"
            :title="$t('setup.process.title')"
            :show-close="false"
            :mask-closable="false"
        >
            <h4 v-t="'setup.process.subtitle'" />
            <br />
            <div v-if="!docker" class="congratulation__additional-config">
                <at-alert
                    class="congratulation__title"
                    :message="$t('setup.process.important_information')"
                    :description="$t('setup.process.info_without_docker')"
                    type="warning"
                />
                <br />
                <div class="congratulation__docker-supervisor">
                    <h4>{{ $t('setup.process.title_supervisor') }}</h4>
                    <pre>
[program:cattr-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /app/backend/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/app/backend/storage/logs/worker.log</pre
                    >
                </div>
                <br />
                <div class="congratulation__docker-cron">
                    <h4>{{ $t('setup.process.title_cron') }}</h4>
                    <pre>
* * * * * su www-data -c "php /app/backend/artisan schedule:run" -s /bin/sh >> /dev/null 2>&1</pre
                    >
                </div>
            </div>
            <template #footer>
                <div class="congratulation__modal-footer">
                    <at-checkbox v-if="!docker" v-model="configConfirmed">
                        {{ $t('setup.process.config_confirmation') }}
                    </at-checkbox>
                    <at-button
                        :loading="!setupFinished"
                        :disabled="!setupFinished || (!docker && !configConfirmed)"
                        @click="$router.push('/')"
                    >
                        {{ $t(setupFinished ? 'setup.process.end_install' : 'setup.process.button_process') }}
                    </at-button>
                </div>
            </template>
        </at-modal>
    </div>
</template>

<script>
    import ApiService from '@/services/api';

    export default {
        name: 'Setup',
        data() {
            return {
                docker: process.env.VUE_APP_DOCKER_VERSION !== 'undefined',
                installationIsInProgress: false,
                configConfirmed: false,
                setupFinished: false,
                currentStep: 0,
                components: [
                    {
                        status: 'wait',
                        name: 'welcome',
                        component: () => import(/* webpackChunkName: "setup/welcome" */ './Setup/Welcome'),
                        storage: {},
                    },
                    {
                        status: 'wait',
                        name: 'backend_ping',
                        component: () => import(/* webpackChunkName: "setup/backend_ping" */ './Setup/BackendPing'),
                        storage: null,
                    },
                    {
                        status: 'wait',
                        name: 'company_settings',
                        component: () =>
                            import(/* webpackChunkName: "setup/company_settings" */ './Setup/CompanySettings'),
                        storage: {},
                    },
                    {
                        status: 'wait',
                        name: 'mail_settings',
                        component: () => import(/* webpackChunkName: "setup/mail_settings" */ './Setup/MailSettings'),
                        storage: {},
                    },
                    {
                        status: 'wait',
                        name: 'database_settings',
                        component: () =>
                            import(/* webpackChunkName: "setup/database_settings" */ './Setup/DatabaseSettings'),
                        storage: {},
                    },
                    {
                        status: 'wait',
                        name: 'account',
                        component: () => import(/* webpackChunkName: "setup/account" */ './Setup/Account'),
                        storage: {},
                    },
                    {
                        status: 'wait',
                        name: 'recaptcha',
                        component: () => import(/* webpackChunkName: "setup/recaptcha" */ './Setup/Recaptcha'),
                        storage: {},
                    },
                ],
            };
        },
        methods: {
            changeStep(value) {
                this.currentStep += value;

                if (value < 0) {
                    this.components[this.currentStep].status = 'wait';
                }
            },
            getStatus(status) {
                if (status === 'success') return 'finish';
                return status;
            },
            completeSetup() {
                this.installationIsInProgress = true;

                new ApiService()
                    .finishSetup({
                        ...this.components.reduce((acc, el) => {
                            if (typeof el.storage !== 'object') {
                                const result = { ...acc };
                                result[el.name] = el.storage;

                                return result;
                            }

                            return { ...acc, ...el.storage };
                        }, {}),
                        origin: window.location.origin,
                    })
                    .then(() => {
                        this.setupFinished = true;
                    });
            },
        },
        computed: {
            isNextStepDisabled() {
                return ['success', 'finish'].indexOf(this.components[this.currentStep].status) === -1;
            },
        },
    };
</script>

<style lang="scss" scoped>
    .form-wrap {
        margin-bottom: $layout-01;
        .header-text {
            margin-bottom: $layout-01;

            &__title,
            &__subtitle {
                text-align: center;
            }
        }
        &__component,
        &__header {
            display: flex;
            justify-content: center;
        }
    }
    .wrap-steps {
        display: flex;
        justify-content: center;
        margin-bottom: $layout-01;
    }
    .wrap-buttons {
        width: 100%;
        display: flex;
        justify-content: space-between;
        margin-top: 2rem;

        &__button {
            margin: 0 20px;
            width: 100%;
            max-width: 100px;
        }
    }
    .congratulation {
        &__additional-config pre {
            width: 100%;
            overflow: auto;
            background: #222;
            color: #fff;
            padding: 5px;
            border-radius: 3px;
        }

        &__modal-footer {
            display: flex;
            justify-content: space-between;
        }
    }
</style>