Source: index.js

/*! meta-admin/modules/index */
/*jslint
    browser, long
*/
/*global
*/
/**
 * index module.
 *
 * @module meta-admin/modules/index
 */
import _ from "underscore";
import clientI18n from "meta-client/modules/i18n";
import clientsComponent from "meta-admin/modules/component/clients";
import config from "./config";
import editorComponent from "meta-admin/modules/component/editor";
import ext from "util-web/modules/ext";
import filesComponent from "meta-admin/modules/component/files";
import i18n from "./i18n";
import i18next from "util-web/modules/i18next";
import keyval from "util-web/modules/keyval";
import ko from "knockout";
import Logger from "js-logger";
import logging from "meta-client/modules/logging";
import loggingComponent from "meta-admin/modules/component/logging";
import loginComponent from "meta-client/modules/component/login";
import metaClient from "meta-client/modules/client";
import metaModel from "meta-core/modules/model";
import nav from "util-web/modules/nav";
import notificationsComponent from "meta-admin/modules/component/notifications";
import osmapComponent from "meta-admin/modules/component/osmap";
import protocol from "meta-core/modules/protocol";
import searcherComponent from "meta-client/modules/component/searcher";
import ui from "util-web/modules/ui";
import usersComponent from "meta-admin/modules/component/users";
import verifyComponent from "meta-client/modules/component/verify";
import viewmodel from "./viewmodel";
import watchdogComponent from "meta-admin/modules/component/watchdog";

const LOG = Logger.get("meta-admin/index");
const TYPE_AND_ACTIONS_STORAGE_KEY = "admin-tanda";
const THEME_STORAGE_KEY = "admin-theme";
const THEME_USE_SYSTEM = "auto";

const vm = {};

vm.currentLocale = i18next.currentLocale;

vm.changeLocale = (locale) => i18next.setLocale(locale);

vm.currentTheme = ko.observable();
vm.currentTheme.subscribe(function (theme) {
    if (THEME_USE_SYSTEM === theme) {
        ui.enableThemeDetection();
    } else if (_.isEmpty(theme) === false) {
        ui.disableThemeDetection();
        ui.setTheme(theme);
    }
});

vm.changeTheme = function (theme) {
    return keyval.set(THEME_STORAGE_KEY, theme).then(() => vm.currentTheme(theme));
};

vm.hasLoaded = ko.observable(false);
vm.isNewVersionAvailable = ko.observable(false);
vm.isActive = ko.observable(false);
vm.isAdmin = ko.observable(false);
vm.doLogout = ko.observable(false);

vm.cacheTypesAndActions = (types, actions) => keyval.set(TYPE_AND_ACTIONS_STORAGE_KEY, {actions, types});

vm.loadTypesAndActions = function () {
    return Promise.all([
        vm.client.search(protocol.searchRequest({
            limit: 0,
            query: metaModel.lucene.META_TYPE_QUERY
        })),
        vm.client.search(protocol.searchRequest({
            limit: 0,
            query: metaModel.lucene.META_ACTION_QUERY
        }))
    ]).then(function (replies) {
        const types = replies[0].metas;
        const actions = replies[1].metas;
        vm.viewmodel.pushTypesAndActions(types, actions);
        vm.cacheTypesAndActions(types, actions);
        vm.isActive(true);
    });
};

vm.onAuth = function () {
    LOG.debug("onAuth");
    return nav.init({}).then(function () {
        vm.isAdmin(vm.client.isMemberOf(metaModel.ADMIN_GROUP));
        if (vm.isAdmin()) {
            return vm.loadTypesAndActions();
        }
        vm.isActive(true);
    });
};

vm.loadCachedTypesAndActions = function () {
    return keyval.get(TYPE_AND_ACTIONS_STORAGE_KEY).then(function (typesAndActions) {
        if (typesAndActions) {
            vm.viewmodel.pushTypesAndActions(typesAndActions.types, typesAndActions.actions);
        }
    });
};

vm.onConnectFailed = function () {
    vm.isAdmin(true);
    vm.isActive(true);
    if (_.isEmpty(vm.viewmodel.types()) && _.isEmpty(vm.viewmodel.actions())) {
        return vm.loadCachedTypesAndActions();
    }
    return Promise.resolve(undefined);
};

vm.logout = function () {
    vm.doLogout(true);
    vm.isActive(false);
    vm.isAdmin(false);
    vm.viewmodel.types.removeAll();
    vm.viewmodel.actions.removeAll();
    return vm.viewmodel.navigateToIndex();
};

vm.reload = () => window.location.reload();

vm.activateGeolocation = function () {
    const mapApi = vm.viewmodel.mapApiProvider();
    if (mapApi) {
        mapApi.activateGeolocation();
    }
};

vm.serviceInfo = ko.observable();

vm.activateServiceInfo = function () {
    return vm.viewmodel.client.getServiceInfo(protocol.serviceInfoRequest()).then(function (reply) {
        vm.serviceInfo(JSON.stringify(reply.info, undefined, 4));
    });
};

vm.onMetaNotification = function (metaNotification) {
    const metaId = metaNotification.log.metaId;
    LOG.debug(`onMetaNotification, metaId=${metaId}`);
    const metaType = metaNotification.log.metaType;
    let metaCollection;
    switch (metaType) {
    case metaModel.META_TYPE_ACTION:
        metaCollection = vm.viewmodel.actions;
        break;
    case metaModel.META_TYPE_TYPE:
        metaCollection = vm.viewmodel.types;
        break;
    default:
        return;
    }
    const predicate = {};
    predicate[metaModel.META_ID] = metaId;
    const existingMeta = _.find(metaCollection(), predicate);
    switch (metaNotification.log.type) {
    case protocol.WRITE_ACTION.CREATE:
        if (Boolean(existingMeta) === false) {
            vm.client.search(protocol.searchRequest({
                limit: 1,
                query: metaId
            })).then(function (searchReply) {
                if (_.isEmpty(searchReply.metas) === false) {
                    metaCollection.push(vm.viewmodel.metaToVm(searchReply.metas[0]));
                }
            });
        }
        break;
    case protocol.WRITE_ACTION.UPDATE:
        if (existingMeta) {
            vm.client.search(protocol.searchRequest({
                limit: 1,
                query: metaId
            })).then(function (searchReply) {
                const meta = searchReply.metas[0];
                switch (metaType) {
                case metaModel.META_TYPE_ACTION:
                    existingMeta.name(meta.name);
                    existingMeta.paramSchema(meta.paramSchema);
                    existingMeta.resultSchema(meta.resultSchema);
                    break;
                case metaModel.META_TYPE_TYPE:
                    existingMeta.name(meta.name);
                    existingMeta.schema(meta.schema);
                    break;
                }
            });
        }
        break;
    case protocol.WRITE_ACTION.DELETE:
        metaCollection.remove((meta) => meta.id === metaId);
        break;
    }
};

vm[protocol.CLIENT_NOTIFICATION] = logging.onClientNotification;
vm[protocol.META_NOTIFICATION] = vm.onMetaNotification;

vm.onNavUpdate = (param) => vm.viewmodel.activeComponent(param);

ext.loadConfig(config).then(function (loadedConfig) {
    vm.config = loadedConfig;
    vm.client = metaClient(vm.config.engine);
    logging.installEngineLogger(vm.client, (
        vm.config.debug
        ? Logger.DEBUG
        : Logger.INFO
    ));
    vm.client.registerOnEvent(vm);
    vm.client.isConnected.subscribe(function (isConnected) {
        if (isConnected) {
            vm.isActive(false);
        }
    });
    vm.viewmodel = viewmodel({client: vm.client, config: vm.config});
    nav.register({
        id: vm.viewmodel.COMPONENTS.INDEX,
        onUpdate: vm.onNavUpdate
    });
    return Promise.all([
        ui.bind({
            components: [
                {isActive: vm.config.map, module: osmapComponent, name: "osmap"},
                {module: clientsComponent, name: "clients"},
                {module: editorComponent, name: "editor"},
                {module: filesComponent, name: "files"},
                {module: loggingComponent, name: "logging"},
                {module: loginComponent, name: "login"},
                {module: notificationsComponent, name: "notifications"},
                {module: searcherComponent, name: "searcher"},
                {module: usersComponent, name: "users"},
                {module: verifyComponent, name: "verify"},
                {module: watchdogComponent, name: "watchdog"}
            ],
            i18NextOptions: {
                debug: vm.config.debug,
                resources: ext.merge(clientI18n, i18n, vm.config.i18n)
            },
            viewmodel: vm
        }),
        ext.registerServiceWorker(() => vm.isNewVersionAvailable(true))
    ]);
}).then(function () {
    document.title = i18next.t("title");
    vm.hasLoaded(true);
    LOG.info(`loaded, version=${__version}`);
    return keyval.get(THEME_STORAGE_KEY);
}).then((theme) => vm.changeTheme(theme ?? THEME_USE_SYSTEM));