Creating your own web-page based Vue.js + UB Server

Creating page

Same as in JQuery lesson:

  1. Create a www subdirectory in the project folder and index.html in it
  2. Add the "inetPub" property to the "httpServer" section in ubConfig.json

Also create app.js and add link to it after closing body tag.

Vue.js and Element UI

Vue.js (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. Unlike other popular frameworks, to get started, all you have to do is drop a single script tag into the page:

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

Then you can start writing Vue code.

Element UI is a Vue based component library for developers, designers and product managers. This library has many components, from simple buttons and input fields to carousels and collapses. Also present bootstrap-like grid layout system. To use library import JavaScript and CSS file in your page. JS file must be imported after Vue.

<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/element-ui/lib/umd/locale/en.js"></script>

Add link to lodash and UB module:

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="/clientRequire/@unitybase/ub-pub/dist/ub-pub.min.js"></script>

Develop vue app

Smallest vue app look like something this:

<div id="app">
  {{ message }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

html

Use element components (tags start with el) to declare next parts of page (inner app div):

  1. Header menu Header menu

    <el-menu default-active="1" mode="horizontal" background-color="#545c64"
                 text-color="#fff"
                 active-text-color="#ffd04b">
            <el-menu-item index="0"><a href="https://unitybase.info/" target="_blank"><img alt="Brand"
                                                                                           src="https://unitybase.info/img/logo.svg"
                                                                                           height="40px"></a></el-menu-item>
            <el-menu-item index="1">Home</el-menu-item>
            <el-menu-item index="2"><a
                    href="https://git-pub.intecracy.com/unitybase/samples/tree/master/courses/tutorial-v5" target="_blank">Tutorials</a>
            </el-menu-item>
            <el-menu-item index="3" v-if="!isLogIn">
                <el-button @click="logInFormVisible = true" type="primary">Log in</el-button>
            </el-menu-item>
            <el-menu-item index="3" v-else>
                <el-button @click="logout" type="primary">Log out</el-button>
            </el-menu-item>
        </el-menu>
    

    v-if directive use to dynamically show or hide element base on condition (log in user or not)

  2. Log in dialog

    login

    <el-dialog title="Log in to City Portal"
                   :visible.sync="logInFormVisible">
            <el-dialog
                    width="30%"
                    title="Failed to log in"
                    :visible.sync="failedToLogInDialogVisible"
                    append-to-body>
            </el-dialog>
            <el-form size="medium">
                <el-form-item label="Login">
                    <el-input v-model="form.login" placeholder="Login"></el-input>
                </el-form-item>
                <el-form-item label="Password">
                    <el-input type="password" v-model="form.pass" placeholder="Password"
                              @keyup.enter.native="login"></el-input>
                </el-form-item>
                <el-button :loading="isLoading" type="primary" @click="login">Continue</el-button>
            </el-form>
        </el-dialog>
    

    Dialog visible if varible logInFormVisible is true. Also we declare sub dialog to show it after wrong login credentials.

  3. Header

    <el-row type="flex" class="row-bg" justify="center">
            <el-col>
                <div style="display: flex;justify-content: center">
                    <h1>{{isLogIn?"Requests":"Welcome to CITY PORTAL!"}}</h1>
                </div>
            </el-col>
    </el-row>
    
  4. Table

    Table

    <el-table
                v-show="isLogIn"
                :data="tableData">
            <el-table-column
                    prop="ID"
                    label="ID">
            </el-table-column>
            <el-table-column
                    prop="reqDate"
                    label="Request Date">
            </el-table-column>
            <el-table-column
                    prop="applicantPhone"
                    label="Applicant Phone">
            </el-table-column>
            <el-table-column
                    prop="applicantInfo"
                    label="Applicant Info">
            </el-table-column>
            <el-table-column
                    prop="status"
                    label="Status">
            </el-table-column>
            <el-table-column
                    prop="reqText"
                    label="Request Text">
            </el-table-column>
            <el-table-column
                    prop="answer"
                    label="Answer">
            </el-table-column>
        </el-table>
    

    :data="tableData" is bind to array of data. If data update, table update automatically.

Script

Add this script to app.js

// if you reload page after login, this variable is true
const wasLogInBeforeReload = localStorage.getItem(location.origin + '/:storedSession') !== null;

const REQ_ENTITY = 'req_reqList';
const REQ_ATTRS = ['ID', 'reqDate', 'applicantPhone', 'applicantInfo', 'status', 'reqText', 'answer'];

//english localisation to element library
ELEMENT.locale(ELEMENT.lang.en);

let Main = {
    data() {
        return {
            form: {
                login: "",
                pass: ""
            },
            logInFormVisible: false,
            failedToLogInDialogVisible: false,
            isLogIn: wasLogInBeforeReload,
            isLoading: false,
            tableData: []
        }
    },
    methods: {
        login: function () {
            this.isLoading = true;
            UB.connect({
                host: window.location.origin,
                allowSessionPersistent: true,
                onCredentialRequired: function (conn, isRepeat) {
                    if (isRepeat) {
                        return Promise.reject(new UB.UBAbortError('invalid password or username'))
                    } else {
                        return Promise.resolve({authSchema: 'UB', login: this.form.login, password: this.form.pass})
                    }
                }.bind(this),
                onAuthorizationFail: function (reason) {
                    this.isLoading = false;
                    this.failedToLogInDialogVisible = true;
                    UB.showErrorWindow(reason);
                }.bind(this),
            }).then(function (conn) {
                this.isLoading = false;
                this.isLogIn = true;
                this.logInFormVisible = false;
                window.$conn = conn;
                this.getRequests()
            }.bind(this))
        },
        logout: function () {
            if (window.$conn) window.$conn
                .logout()
                .then(function () {
                    this.isLogIn = false;
                    this.logInFormVisible = true;
                }.bind(this))
        },
        getRequests: function () {
            window.$conn.Repository(REQ_ENTITY).attrs(REQ_ATTRS).select()
                .then(function (data) {
                    this.tableData = data.map(req => {
                        req.reqDate = req.reqDate.toLocaleDateString('ru-RU');
                        return req;
                    });
                }.bind(this))
        }
    },
    //this part execute after page load
    mounted: function () {
        //auto login and show requests after reload logged page
        if (wasLogInBeforeReload) {
            UB.connect({
                host: window.location.origin,
                allowSessionPersistent: true,
                onAuthorizationFail: function (reason) {
                    UB.showErrorWindow(reason)
                }
            }).then(function (conn) {
                window.$conn = conn;
                this.getRequests();
            }.bind(this))
        }
    }
};
let Ctor = Vue.extend(Main);
new Ctor().$mount('#app');

Now project is available at http://localhost:8881.