<commit_before>/**
 * Handles the initial creation of the workspace screen.
 * @param path - path to iframe
 * @param collectionId
 * @param menu - opens a specific menu
 * @param collectionData - JSON of the currently active collection
 * @param stopEventListener - separates the link between editor and iframe
 * @returns {boolean}
 **/

function createWorkspace(path, collectionId, menu, collectionData, stopEventListener) {
    var safePath = '';

    $("#working-on").on('click', function () {
    }); // add event listener to mainNav

    if (stopEventListener) {
        document.getElementById('iframe').onload = function () {
            var browserLocation = document.getElementById('iframe').contentWindow.location.href;
            $('.browser-location').val(browserLocation);
            var iframeEvent = document.getElementById('iframe').contentWindow;
            iframeEvent.removeEventListener('click', Florence.Handler, true);
        };
        return false;
    } else {
        var currentPath = '';
        if (path) {
            currentPath = path;
            safePath = checkPathSlashes(currentPath);
        }

        Florence.globalVars.pagePath = safePath;
        if (Florence.globalVars.welsh !== true) {
            document.cookie = "lang=" + "en;path=/";
        } else {
            document.cookie = "lang=" + "cy;path=/";
        }
        Florence.refreshAdminMenu();

        // If data visualisation load preview but ending with '/' so that vis loads correctly
        if (collectionData && collectionData.collectionOwner == "DATA_VISUALISATION") {
            safePath += "/";
            path += "/";
        }

        var workSpace = templates.workSpace(Florence.babbageBaseUrl + safePath);
        $('.section').html(workSpace);

        // Store nav objects
        var $nav = $('.js-workspace-nav'),
            $navItem = $nav.find('.js-workspace-nav__item');

        // Set browse panel to full height to show loading icon
        $('.loader').css('margin-top', '84px');
        $('.workspace-menu').height($('.workspace-nav').height());

        // Detect click on preview, stopping browsing around preview from getting rid of unsaved data accidentally
        detectPreviewClick();

        // Detect changes to preview and handle accordingly
        processPreviewLoad(collectionId, collectionData);

        // Update preview URL on initial load of workspace
        updateBrowserURL(path);

        if (Florence.globalVars.welsh !== true) {
            $('#nav--workspace__welsh').empty().append('Language: English');
        } else {
            $('#nav--workspace__welsh').empty().append('Language: Welsh');
        }

        //click handlers
        $navItem.click(function () {
            menu = '';
            if (Florence.Editor.isDirty) {
                swal({
                    title: "Warning",
                    text: "You have unsaved changes. Are you sure you want to continue?",
                    type: "warning",
                    showCancelButton: true,
                    confirmButtonText: "Continue",
                    cancelButtonText: "Cancel"
                }, function (result) {
                    if (result === true) {
                        Florence.Editor.isDirty = false;
                        processMenuClick(this);
                    } else {
                        return false;
                    }
                });
            } else {
                processMenuClick(this);
            }
        });

        function processMenuClick(clicked) {
            var menuItem = $(clicked);

            $navItem.removeClass('selected');
            menuItem.addClass('selected');

            if (menuItem.is('#browse')) {
                loadBrowseScreen(collectionId, 'click', collectionData);
            } else if (menuItem.is('#create')) {
                Florence.globalVars.pagePath = getPreviewUrl();
                var type = false;
                loadCreateScreen(Florence.globalVars.pagePath, collectionId, type, collectionData);
            } else if (menuItem.is('#edit')) {
                Florence.globalVars.pagePath = getPreviewUrl();
                loadPageDataIntoEditor(Florence.globalVars.pagePath, Florence.collection.id);
            } else if (menuItem.is('#import')) {
                loadImportScreen(Florence.collection.id);
            } else {
                loadBrowseScreen(collectionId, false, collectionData);
            }
        }

        $('#nav--workspace__welsh').on('click', function () {
            Florence.globalVars.welsh = Florence.globalVars.welsh === false ? true : false;
            createWorkspace(Florence.globalVars.pagePath, collectionId, 'browse');
        });

        $('.workspace-menu').on('click', '.btn-browse-create', function () {
            var dest = $('.tree-nav-holder ul').find('.js-browse__item.selected').attr('data-url');
            // var spanType = $(this).parent().prev('span');
            var spanType = $(this).closest('.js-browse__item').find('.js-browse__item-title:first');
            var typeClass = spanType[0].attributes[0].nodeValue;
            var typeGroup = typeClass.match(/--(\w*)$/);
            var type = typeGroup[1];
            Florence.globalVars.pagePath = dest;
            $navItem.removeClass('selected');
            $("#create").addClass('selected');
            loadCreateScreen(Florence.globalVars.pagePath, collectionId, type, collectionData);
        });

        $('.workspace-menu').on('click', '.btn-browse-delete', function () {
            var $parentItem = $('.tree-nav-holder ul').find('.js-browse__item.selected');
            var $parentContainer = $parentItem.find('.page__container.selected');
            var $button = $parentContainer.find('.btn-browse-delete');
            var dest = $parentItem.attr('data-url');
            var spanType = $(this).parent().prev('span');
            var title = spanType.html();
            addDeleteMarker(dest, title, function() {
                $parentContainer.addClass('animating').addClass('deleted');
                toggleDeleteRevertButton($parentContainer);
                toggleDeleteRevertChildren($parentItem);

                // Stops animation happening anytime other than when going between delete/undo delete
                $parentContainer.one("webkitTransitionEnd transitionEnd", function() {
                    $parentContainer.removeClass('animating');
                });
            });
        });

        $('.workspace-menu').on('click', '.btn-browse-delete-revert', function () {
            var $parentItem = $('.tree-nav-holder ul').find('.js-browse__item.selected');
            var $parentContainer = $parentItem.find('.page__container.selected');
            var $button = $parentContainer.find('.btn-browse-delete-revert');
            var dest = $parentItem.attr('data-url');
            removeDeleteMarker(dest, function() {
                $parentContainer.addClass('animating').removeClass('deleted');
                toggleDeleteRevertButton($parentContainer);
                toggleDeleteRevertChildren($parentItem);

                // Stops animation happening anytime other than when going between delete/undo delete
                $parentContainer.one("webkitTransitionEnd transitionEnd", function() {
                    $parentContainer.removeClass('animating');
                });
            });
        });

        $('.workspace-menu').on('click', '.btn-browse-move', function() {
            var $parentItem = $('.tree-nav-holder ul').find('.js-browse__item.selected'),
                fromUrl = $parentItem.attr('data-url');

            moveBrowseNode(fromUrl);
        });

        $('.workspace-menu').on('click', '.btn-browse-create-datavis', function () {
            var dest = '/visualisations';
            var type = 'visualisation';
            Florence.globalVars.pagePath = dest;
            loadCreateScreen(Florence.globalVars.pagePath, collectionId, type, collectionData);
        });

        $('.workspace-menu').on('click', '.btn-browse-edit', function () {
            var dest = $('.tree-nav-holder ul').find('.js-browse__item.selected').attr('data-url');
            Florence.globalVars.pagePath = dest;
            $navItem.removeClass('selected');
            $("#edit").addClass('selected');
            loadPageDataIntoEditor(Florence.globalVars.pagePath, collectionId);
        });

        $('.workspace-menu').on('click', '.js-browse__menu', function() {
            var $thisItem = $('.js-browse__item.selected .page__container.selected'),
                $thisBtn = $thisItem.find('.js-browse__menu'),
                $thisMenu = $thisBtn.next('.page__menu'),
                menuHidden;

            function toggleMenu() {
                $thisBtn.toggleClass('active').children('.hamburger-icon__span').toggleClass('active');
                $thisItem.find('.js-browse__buttons--primary').toggleClass('active');
                $thisMenu.toggleClass('active');
            }

            // Toggle menu on click
            toggleMenu();

            // Shut menu if another item or button is clicked
            $('.js-browse__item-title, .btn-browse-move, .btn-browse-delete').on('click', function() {
                if (!menuHidden) {
                    toggleMenu();
                    menuHidden = true;
                }
            });
        });

        if (menu === 'edit') {
            $navItem.removeClass('selected');
            $("#edit").addClass('selected');
            loadPageDataIntoEditor(Florence.globalVars.pagePath, collectionId);
        } else if (menu === 'browse') {
            $navItem.removeClass('selected');
            $("#browse").addClass('selected');
            loadBrowseScreen(collectionId, 'click', collectionData);
        }
        //};
    }
}

// SHOULD BE REPLACED BY 'onIframeLoad' -  Bind click event to iframe element and run global Florence.Handler
function detectPreviewClick() {
    var iframeEvent = document.getElementById('iframe').contentWindow;
    iframeEvent.addEventListener('click', Florence.Handler, true);
}

// Full collection of functions to run on iframe load
function processPreviewLoad(collectionId, collectionData) {
    onIframeLoad(function (event) {
        var $iframe = $('#iframe'), // iframe element in DOM, check length later to ensure it's on the page before continuing
            $browse = $('#browse'); // 'Browse' menu tab, check later if it's selected

        // Check it is a load event and that iframe is in the DOM still before processing the load
        if (event.data == "load" && $iframe.length) {
            // Check whether page URL is different and then load editor or update browse tree
            checkForPageChanged(function (newUrl) {
                var safeUrl = checkPathSlashes(newUrl),
                    selectedItem = $('.workspace-browse li.selected').attr('data-url'); // Get active node in the browse tree

                Florence.globalVars.pagePath = safeUrl;

                if ($('.workspace-edit').length || $('.workspace-create').length) {
                    // Switch to browse screen if navigating around preview whilst on create or edit tab
                    loadBrowseScreen(collectionId, 'click', collectionData);

                    // TODO temporary fix, remove this when data vis has been refactored to not use trailing slashes (difference between URL is causing visualisations to sometimes switch to browse tab on save)
                    if (Florence.Authentication.userType() == "DATA_VISUALISATION") {
                        return false;
                    }
                }
                else if ($('.workspace-browse').length && selectedItem != Florence.globalVars.pagePath) {
                    // Only update browse tree of on 'browse' tab and preview and active node don't already match
                    treeNodeSelect(safeUrl);
                }
            });
            updateBrowserURL(); // Update browser preview URL

            if ($browse.hasClass('selected')) {
                browseScrollPos(); // Update browse tree scroll position
            }
        }
    });
}

// Reusable iframe startload event - uses message sent up form babbage on window.load
function onIframeLoad(runFunction) {
    window.addEventListener("message", function (event) {
        runFunction(event);
    });
}

// Update the scroll position of the browse tree if selected item off screen
function browseScrollPos() {
    var $selectedItem = $('.workspace-browse li.selected .page__container.selected'),
        $browseTree = $('.workspace-browse');

    if ($selectedItem.length) {
        var selectedTop = $selectedItem.offset().top,
            selectedBottom = selectedTop + $selectedItem.height(),
            browseTop = $browseTree.offset().top,
            browseBottom = browseTop + $browseTree.height(),
            navHeight = $('.nav').height();

        if (selectedTop < browseTop) {
            console.log('Item was outside of viewable browse tree');
            $browseTree.scrollTop($browseTree.scrollTop() + (selectedTop) - (navHeight / 2));
        } else if (selectedBottom > browseBottom) {
            console.log('Item was outside of viewable browse tree');
            $browseTree.scrollTop(selectedBottom - (navHeight / 2) - $selectedItem.height())
        }
    }
}

function updateBrowserURL(url) {
    if(!url) {
        url = Florence.globalVars.pagePath;
    }
    $('.browser-location').val(Florence.babbageBaseUrl + url);
}

// toggle delete button from 'delete' to 'revert' for content marked as to be deleted and remove/show other buttons in item
function toggleDeleteRevertButton($container) {
    $container.find('.btn-browse-delete-revert, .js-browse__buttons--primary, .js-browse__buttons--secondary').toggle();
}

// Toggle displaying children as deleted or not deleted
function toggleDeleteRevertChildren($item) {
    var $childContainer = $item.find('.js-browse__item .page__container'),
        isDeleting = $item.children('.page__container').hasClass('deleted');

    if (isDeleting) {
        $childContainer.addClass('deleted');
    } else {
        $childContainer.removeClass('deleted');

        // If a child item has previously been deleted but is being shown by a parent then undo the toggle buttons
        if ($childContainer.find('.btn-browse-delete-revert').length) {
            // toggleDeleteRevertButton($childContainer.find('.btn-browse-delete-revert'));
            toggleDeleteRevertButton($childContainer);
        }
    }

    $childContainer.find('.page__buttons').toggleClass('deleted');
}

<commit_msg>Again... fix visualisations returning to browse on save<commit_after>/**
 * Handles the initial creation of the workspace screen.
 * @param path - path to iframe
 * @param collectionId
 * @param menu - opens a specific menu
 * @param collectionData - JSON of the currently active collection
 * @param stopEventListener - separates the link between editor and iframe
 * @returns {boolean}
 **/

function createWorkspace(path, collectionId, menu, collectionData, stopEventListener) {
    var safePath = '';

    $("#working-on").on('click', function () {
    }); // add event listener to mainNav

    if (stopEventListener) {
        document.getElementById('iframe').onload = function () {
            var browserLocation = document.getElementById('iframe').contentWindow.location.href;
            $('.browser-location').val(browserLocation);
            var iframeEvent = document.getElementById('iframe').contentWindow;
            iframeEvent.removeEventListener('click', Florence.Handler, true);
        };
        return false;
    } else {
        var currentPath = '';
        if (path) {
            currentPath = path;
            safePath = checkPathSlashes(currentPath);
        }

        Florence.globalVars.pagePath = safePath;
        if (Florence.globalVars.welsh !== true) {
            document.cookie = "lang=" + "en;path=/";
        } else {
            document.cookie = "lang=" + "cy;path=/";
        }
        Florence.refreshAdminMenu();

        // If data visualisation load preview but ending with '/' so that vis loads correctly
        if (collectionData && collectionData.collectionOwner == "DATA_VISUALISATION") {
            safePath += "/";
            path += "/";
        }

        var workSpace = templates.workSpace(Florence.babbageBaseUrl + safePath);
        $('.section').html(workSpace);

        // Store nav objects
        var $nav = $('.js-workspace-nav'),
            $navItem = $nav.find('.js-workspace-nav__item');

        // Set browse panel to full height to show loading icon
        $('.loader').css('margin-top', '84px');
        $('.workspace-menu').height($('.workspace-nav').height());

        // Detect click on preview, stopping browsing around preview from getting rid of unsaved data accidentally
        detectPreviewClick();

        // Detect changes to preview and handle accordingly
        processPreviewLoad(collectionId, collectionData);

        // Update preview URL on initial load of workspace
        updateBrowserURL(path);

        if (Florence.globalVars.welsh !== true) {
            $('#nav--workspace__welsh').empty().append('Language: English');
        } else {
            $('#nav--workspace__welsh').empty().append('Language: Welsh');
        }

        //click handlers
        $navItem.click(function () {
            menu = '';
            if (Florence.Editor.isDirty) {
                swal({
                    title: "Warning",
                    text: "You have unsaved changes. Are you sure you want to continue?",
                    type: "warning",
                    showCancelButton: true,
                    confirmButtonText: "Continue",
                    cancelButtonText: "Cancel"
                }, function (result) {
                    if (result === true) {
                        Florence.Editor.isDirty = false;
                        processMenuClick(this);
                    } else {
                        return false;
                    }
                });
            } else {
                processMenuClick(this);
            }
        });

        function processMenuClick(clicked) {
            var menuItem = $(clicked);

            $navItem.removeClass('selected');
            menuItem.addClass('selected');

            if (menuItem.is('#browse')) {
                loadBrowseScreen(collectionId, 'click', collectionData);
            } else if (menuItem.is('#create')) {
                Florence.globalVars.pagePath = getPreviewUrl();
                var type = false;
                loadCreateScreen(Florence.globalVars.pagePath, collectionId, type, collectionData);
            } else if (menuItem.is('#edit')) {
                Florence.globalVars.pagePath = getPreviewUrl();
                loadPageDataIntoEditor(Florence.globalVars.pagePath, Florence.collection.id);
            } else if (menuItem.is('#import')) {
                loadImportScreen(Florence.collection.id);
            } else {
                loadBrowseScreen(collectionId, false, collectionData);
            }
        }

        $('#nav--workspace__welsh').on('click', function () {
            Florence.globalVars.welsh = Florence.globalVars.welsh === false ? true : false;
            createWorkspace(Florence.globalVars.pagePath, collectionId, 'browse');
        });

        $('.workspace-menu').on('click', '.btn-browse-create', function () {
            var dest = $('.tree-nav-holder ul').find('.js-browse__item.selected').attr('data-url');
            // var spanType = $(this).parent().prev('span');
            var spanType = $(this).closest('.js-browse__item').find('.js-browse__item-title:first');
            var typeClass = spanType[0].attributes[0].nodeValue;
            var typeGroup = typeClass.match(/--(\w*)$/);
            var type = typeGroup[1];
            Florence.globalVars.pagePath = dest;
            $navItem.removeClass('selected');
            $("#create").addClass('selected');
            loadCreateScreen(Florence.globalVars.pagePath, collectionId, type, collectionData);
        });

        $('.workspace-menu').on('click', '.btn-browse-delete', function () {
            var $parentItem = $('.tree-nav-holder ul').find('.js-browse__item.selected');
            var $parentContainer = $parentItem.find('.page__container.selected');
            var $button = $parentContainer.find('.btn-browse-delete');
            var dest = $parentItem.attr('data-url');
            var spanType = $(this).parent().prev('span');
            var title = spanType.html();
            addDeleteMarker(dest, title, function() {
                $parentContainer.addClass('animating').addClass('deleted');
                toggleDeleteRevertButton($parentContainer);
                toggleDeleteRevertChildren($parentItem);

                // Stops animation happening anytime other than when going between delete/undo delete
                $parentContainer.one("webkitTransitionEnd transitionEnd", function() {
                    $parentContainer.removeClass('animating');
                });
            });
        });

        $('.workspace-menu').on('click', '.btn-browse-delete-revert', function () {
            var $parentItem = $('.tree-nav-holder ul').find('.js-browse__item.selected');
            var $parentContainer = $parentItem.find('.page__container.selected');
            var $button = $parentContainer.find('.btn-browse-delete-revert');
            var dest = $parentItem.attr('data-url');
            removeDeleteMarker(dest, function() {
                $parentContainer.addClass('animating').removeClass('deleted');
                toggleDeleteRevertButton($parentContainer);
                toggleDeleteRevertChildren($parentItem);

                // Stops animation happening anytime other than when going between delete/undo delete
                $parentContainer.one("webkitTransitionEnd transitionEnd", function() {
                    $parentContainer.removeClass('animating');
                });
            });
        });

        $('.workspace-menu').on('click', '.btn-browse-move', function() {
            var $parentItem = $('.tree-nav-holder ul').find('.js-browse__item.selected'),
                fromUrl = $parentItem.attr('data-url');

            moveBrowseNode(fromUrl);
        });

        $('.workspace-menu').on('click', '.btn-browse-create-datavis', function () {
            var dest = '/visualisations';
            var type = 'visualisation';
            Florence.globalVars.pagePath = dest;
            loadCreateScreen(Florence.globalVars.pagePath, collectionId, type, collectionData);
        });

        $('.workspace-menu').on('click', '.btn-browse-edit', function () {
            var dest = $('.tree-nav-holder ul').find('.js-browse__item.selected').attr('data-url');
            Florence.globalVars.pagePath = dest;
            $navItem.removeClass('selected');
            $("#edit").addClass('selected');
            loadPageDataIntoEditor(Florence.globalVars.pagePath, collectionId);
        });

        $('.workspace-menu').on('click', '.js-browse__menu', function() {
            var $thisItem = $('.js-browse__item.selected .page__container.selected'),
                $thisBtn = $thisItem.find('.js-browse__menu'),
                $thisMenu = $thisBtn.next('.page__menu'),
                menuHidden;

            function toggleMenu() {
                $thisBtn.toggleClass('active').children('.hamburger-icon__span').toggleClass('active');
                $thisItem.find('.js-browse__buttons--primary').toggleClass('active');
                $thisMenu.toggleClass('active');
            }

            // Toggle menu on click
            toggleMenu();

            // Shut menu if another item or button is clicked
            $('.js-browse__item-title, .btn-browse-move, .btn-browse-delete').on('click', function() {
                if (!menuHidden) {
                    toggleMenu();
                    menuHidden = true;
                }
            });
        });

        if (menu === 'edit') {
            $navItem.removeClass('selected');
            $("#edit").addClass('selected');
            loadPageDataIntoEditor(Florence.globalVars.pagePath, collectionId);
        } else if (menu === 'browse') {
            $navItem.removeClass('selected');
            $("#browse").addClass('selected');
            loadBrowseScreen(collectionId, 'click', collectionData);
        }
        //};
    }
}

// SHOULD BE REPLACED BY 'onIframeLoad' -  Bind click event to iframe element and run global Florence.Handler
function detectPreviewClick() {
    var iframeEvent = document.getElementById('iframe').contentWindow;
    iframeEvent.addEventListener('click', Florence.Handler, true);
}

// Full collection of functions to run on iframe load
function processPreviewLoad(collectionId, collectionData) {
    onIframeLoad(function (event) {
        var $iframe = $('#iframe'), // iframe element in DOM, check length later to ensure it's on the page before continuing
            $browse = $('#browse'); // 'Browse' menu tab, check later if it's selected

        // Check it is a load event and that iframe is in the DOM still before processing the load
        if (event.data == "load" && $iframe.length) {
            // Check whether page URL is different and then load editor or update browse tree
            checkForPageChanged(function (newUrl) {
                var safeUrl = checkPathSlashes(newUrl),
                    selectedItem = $('.workspace-browse li.selected').attr('data-url'); // Get active node in the browse tree

                Florence.globalVars.pagePath = safeUrl;

                if ($('.workspace-edit').length || $('.workspace-create').length) {
                    // TODO temporary fix, remove this when data vis has been refactored to not use trailing slashes (difference between URL is causing visualisations to sometimes switch to browse tab on save)
                    if (Florence.Authentication.userType() == "DATA_VISUALISATION") {
                        return false;
                    }

                    // Switch to browse screen if navigating around preview whilst on create or edit tab
                    loadBrowseScreen(collectionId, 'click', collectionData);
                }
                else if ($('.workspace-browse').length && selectedItem != Florence.globalVars.pagePath) {
                    // Only update browse tree of on 'browse' tab and preview and active node don't already match
                    treeNodeSelect(safeUrl);
                }
            });
            updateBrowserURL(); // Update browser preview URL

            if ($browse.hasClass('selected')) {
                browseScrollPos(); // Update browse tree scroll position
            }
        }
    });
}

// Reusable iframe startload event - uses message sent up form babbage on window.load
function onIframeLoad(runFunction) {
    window.addEventListener("message", function (event) {
        runFunction(event);
    });
}

// Update the scroll position of the browse tree if selected item off screen
function browseScrollPos() {
    var $selectedItem = $('.workspace-browse li.selected .page__container.selected'),
        $browseTree = $('.workspace-browse');

    if ($selectedItem.length) {
        var selectedTop = $selectedItem.offset().top,
            selectedBottom = selectedTop + $selectedItem.height(),
            browseTop = $browseTree.offset().top,
            browseBottom = browseTop + $browseTree.height(),
            navHeight = $('.nav').height();

        if (selectedTop < browseTop) {
            console.log('Item was outside of viewable browse tree');
            $browseTree.scrollTop($browseTree.scrollTop() + (selectedTop) - (navHeight / 2));
        } else if (selectedBottom > browseBottom) {
            console.log('Item was outside of viewable browse tree');
            $browseTree.scrollTop(selectedBottom - (navHeight / 2) - $selectedItem.height())
        }
    }
}

function updateBrowserURL(url) {
    if(!url) {
        url = Florence.globalVars.pagePath;
    }
    $('.browser-location').val(Florence.babbageBaseUrl + url);
}

// toggle delete button from 'delete' to 'revert' for content marked as to be deleted and remove/show other buttons in item
function toggleDeleteRevertButton($container) {
    $container.find('.btn-browse-delete-revert, .js-browse__buttons--primary, .js-browse__buttons--secondary').toggle();
}

// Toggle displaying children as deleted or not deleted
function toggleDeleteRevertChildren($item) {
    var $childContainer = $item.find('.js-browse__item .page__container'),
        isDeleting = $item.children('.page__container').hasClass('deleted');

    if (isDeleting) {
        $childContainer.addClass('deleted');
    } else {
        $childContainer.removeClass('deleted');

        // If a child item has previously been deleted but is being shown by a parent then undo the toggle buttons
        if ($childContainer.find('.btn-browse-delete-revert').length) {
            // toggleDeleteRevertButton($childContainer.find('.btn-browse-delete-revert'));
            toggleDeleteRevertButton($childContainer);
        }
    }

    $childContainer.find('.page__buttons').toggleClass('deleted');
}

<|endoftext|>


<commit_before>import React from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import {namespaceConfig} from 'fast-redux'
import Link from 'next/link'

const DEFAULT_STATE = {version: 1}

const {actionCreator, getState: getAboutState} = namespaceConfig('about', DEFAULT_STATE)

const bumpVersion = actionCreator('bumpVersion', function(state, increment) {
  return {...state, version: state.version + increment}
})

const About = ({ version, bumpVersion }) => (

About us

Current version: {version}

<button onClick={(e) => bumpVersion(1)}>Bump version!</button>

    <Link href='/'>Homepage</Link>

)

function mapStateToProps (state) {
  return getAboutState(state, 'version')
}

function mapDispatchToProps (dispatch) {
  return bindActionCreators({ bumpVersion }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(About)
<commit_msg>Fix failing linter tests (#5257)<commit_after>import React from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import {namespaceConfig} from 'fast-redux'
import Link from 'next/link'

const DEFAULT_STATE = {version: 1}

const {actionCreator, getState: getAboutState} = namespaceConfig('about', DEFAULT_STATE)

const bumpVersion = actionCreator('bumpVersion', function (state, increment) {
  return {...state, version: state.version + increment}
})

const About = ({ version, bumpVersion }) => (

About us

Current version: {version}

<button onClick={(e) => bumpVersion(1)}>Bump version!</button>

    <Link href='/'>Homepage</Link>

)

function mapStateToProps (state) {
  return getAboutState(state, 'version')
}

function mapDispatchToProps (dispatch) {
  return bindActionCreators({ bumpVersion }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(About)
<|endoftext|>


<commit_before>/**
 * GlobalMetadata.js
 *
 * Module to global metadata.
 */
var GlobalMetadata = (function () {

    function populateTags(metadataProfileGeneralData) {

        // We will stash our required attribute names here.
        var required = [];

        var metadataGroupsMap = new Map();
        for (var i = 0; i < metadataProfileGeneralData.length; i++) {
            var attribute = metadataProfileGeneralData[i];
            var metadataGroup = attribute.metadataGroup;
            var complianceLevel = attribute.complianceLevel;
            var attributeName = attribute.attributeName;
            var displayName = attribute.displayName;
            var metadataValueType = attribute.metadataValueType;
            if (!displayName) {
                displayName = attributeName;
            }
            var description = attribute.description;
            var exampleValues = attribute.exampleValues;

            if (complianceLevel === "required") {
                required.push(attributeName + "__" + metadataGroup);
            }

            if (complianceLevel === "optional") {
                complianceLevel = "additional";
            }

            var tag =
                "
\n" +
                "   \n" +
                "       " + displayName + "\n" +
                "       (" + complianceLevel + ")\n";
            if (description  || exampleValues) {
                tag = tag + "       \n";
            }
            tag = tag +
                "
\n" +
                "       <input class=\"" + complianceLevel + "\" type=\"text\" name=\"" + attributeName + "\" id=\"" + attributeName + "__" + metadataGroup+ "\" value=\"\"/>\n" +
                "   \n" +
                "   \n" +
                "
\n";

            if (metadataGroupsMap.has(metadataGroup)) {
                // Already exists.

                // get the compliance level map.
                var complianceLevelsMap =  metadataGroupsMap.get(metadataGroup);

                if (complianceLevelsMap.has(complianceLevel)) {
                    // Already exists.

                    // Get array of tags.
                    var tags =  complianceLevelsMap.get(complianceLevel);
                    tags.push(tag);

                } else {
                    // Doesn't exist in the compliance level map yet.

                    // Add tag to compliance level map.
                    complianceLevelsMap.set(complianceLevel, [tag]);

                    // Add the compliance levels map to the metadata group map.
                    metadataGroupsMap.set(metadataGroup, complianceLevelsMap);
                }

            } else {
                // Doesn't exist in the metadata group map yet.

                // Create compliance levels map and add the tag string to the inner array.
                var complianceLevelsMap = new Map();
                complianceLevelsMap.set(complianceLevel, [tag]);

                // Add the compliance levels map to the metadata group map.
                metadataGroupsMap.set(metadataGroup, complianceLevelsMap);
            }
        }

        // Store required globals.
        storeData("_g", required);

        // Attach tags to the DOM.
        attachToDom(metadataGroupsMap);
        // Bind general metadata events.
        bindGeneralMetadataEvents()
    }

    function attachToDom(metadataGroupsMap) {
        for (const [metadataGroup, complianceLevelsMap] of metadataGroupsMap.entries()) {
            var title = metadataGroup.replace(/_/g, ' ');
            if (title === "root") {
                title = "general";
            }
            title = title.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
            $("#generalMetadataAssignment").append(
                "
\n" +
                "
" + title + "
\n" +
                "

\n" +
                "
\n"
            );
            for (const [complianceLevel, tags] of complianceLevelsMap.entries()) {
                for (var i = 0; i < tags.length; i++) {
                    $("#generalMetadataAssignment #" + metadataGroup + " ul").append(tags[i]);
                }
            }
        }
        populateDataFromStorage();
    }

    function bindGeneralMetadataEvents() {
        $("#generalMetadataAssignment input").focusout(function () {
            storeGlobalMetadataEntry($(this).attr("id"), $(this).val());
            isComplete();
        });
    }

    function isComplete() {
        if (testCompleteness()) {
            // Add stored global metadata info to input tag value.
            $("#globalMetadata").val(JSON.stringify(getStoredGlobalMetadata()));

            // remove disabled status for submit button.
            $("input[type=submit]#Next").removeAttr("disabled");
            // remove disabled class for submit button.
            $("input[type=submit]#Next").removeClass("disabled");
        }
    }

    function testCompleteness() {
        var required = getStoredData("_g").split(/,/g);

        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();
        var stored = [];
        Object.keys(globalMetadata).forEach(function(key) {
            stored.push(key);
        });

        for (var i = 0; i < required.length; i++) {
            if (!stored.includes(required[i])) {
                return false;
            }
        }
        return true;
    }

    function populateDataFromStorage() {
        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();
        Object.keys(globalMetadata).forEach(function(key) {
            var inputTag = $("#generalMetadataAssignment input#" + key);
            $(inputTag).val(globalMetadata[key]);
        });
        toggleCategories();
    }

    function toggleCategories() {
        $("#generalMetadataAssignment input").each(function () {
            var inputTag = $(this);
            $(inputTag).prevAll().each(function () {
                if($(this).prop("tagName") === "SMALL") {
                    var complianceLevel = $(this).text();
                    if (complianceLevel === "(required)") {
                        if (!$(inputTag).val().match(/\w+/)) {
                            $(inputTag).parents().each(function () {
                                var parent = (this);
                                if($(parent).prop("tagName") === "UL") {
                                    $(parent).removeClass("hideMe");
                                    var categoryTitle = $(parent).prev();
                                    $(categoryTitle).removeClass("expand");
                                    $(categoryTitle).addClass("collapse");
                                }
                            });
                        }
                    }
                }
            });
        });
    }

    function storeGlobalMetadataEntry(key, value) {
        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();

        // Assign the provided object key to the provided value.
        globalMetadata[key] = value;

        // Update the stored global data.
        updateStoredGlobalMetadata(globalMetadata);
    }

    function removeGlobaMetadataEntry(key) {
        // Get the stored global data.
        var globalMetadata =getStoredGlobalMetadata();

        // Delete the entry using the provided object key.
        delete globalMetadata[key];

        // Update the stored global data.
        updateStoredGlobalMetadata(globalMetadata);
    }

   function getGlobalDataMetadataEntry(key) {
        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();

        return globalMetadata[key];
    }

    function getStoredGlobalMetadata() {
        // Get the stored global data.
        var globalMetadata = getStoredData("globalMetadata");

        if (globalMetadata === null) {
            // This shouldn't happen; if we are here then something has gone very wrong (this info should be in the stored).
            displayErrorMessage("Unable to access stored variable matadata.");
        } else {
            // Un-stringify.
            return JSON.parse(globalMetadata);
        }
    }

    function updateStoredGlobalMetadata(globalMetadata) {
        // Stringify and stored data.
        storeData("globalMetadata", JSON.stringify(globalMetadata));
    }

    function displayErrorMessage(message) {
        $("#dialog #variableNameTypeAssignment").find("label.error").text(message + "  Please contact the Rosetta site administrator.");
    }

    // Expose these functions.
    return {
        populateTags: populateTags
    };

})();
<commit_msg>modified to add map sorting and reimplementation of tags<commit_after>/**
 * GlobalMetadata.js
 *
 * Module to global metadata.
 */
var GlobalMetadata = (function () {

    /**
     * Uses the server-sent metadata profile information to create the global variable tags.
     *
     * @param metadataProfileGeneralData  The array of global variables.
     */
    function populateTags(metadataProfileGeneralData) {

        // We will stash our required variable names here.
        var required = [];

        // We will stash our tags in here by group.
        var metadataGroupsMap = new Map();

        for (var i = 0; i < metadataProfileGeneralData.length; i++) {
            var variable = metadataProfileGeneralData[i];
            var metadataGroup = variable.metadataGroup;
            var complianceLevel = variable.complianceLevel;
            var attributeName = variable.attributeName;
            var displayName = variable.displayName;
            // If there is no display name provided, use the attribute name.
            if (!displayName) {
                displayName = attributeName.replace(/_/g, ' ');
            }
            var description = variable.description;
            var exampleValues = variable.exampleValues;

            // Push required variables onto the required array (used later for validation).
            if (complianceLevel === "required") {
                required.push(attributeName + "__" + metadataGroup);
            }
            // We prefer the term additional to optional.
            if (complianceLevel === "optional") {
                complianceLevel = "additional";
            }

            // Create the tag.
            var tag =
                "
\n" +
                "   \n" +
                "       " + displayName + "\n";
            if (description  || exampleValues) {
                tag = tag + "       \n";
            }
            tag = tag +
                "
\n" +
                "       <input type=\"text\" name=\"" + attributeName + "\" id=\"" + attributeName + "__" + metadataGroup+ "\" value=\"\"/>\n" +
                "   \n" +
                "   \n" +
                "
\n";

            // Assign to the correct map entry.
            if (metadataGroupsMap.has(metadataGroup)) {
                // Already exists.

                // get the compliance level map.
                var complianceLevelsMap =  metadataGroupsMap.get(metadataGroup);

                if (complianceLevelsMap.has(complianceLevel)) {
                    // Already exists.

                    // Get array of tags.
                    var tags =  complianceLevelsMap.get(complianceLevel);
                    tags.push(tag);

                } else {
                    // Doesn't exist in the compliance level map yet.

                    // Add tag to compliance level map.
                    complianceLevelsMap.set(complianceLevel, [tag]);

                    // Add the compliance levels map to the metadata group map.
                    metadataGroupsMap.set(metadataGroup, complianceLevelsMap);
                }

            } else {
                // Doesn't exist in the metadata group map yet.

                // Create compliance levels map and add the tag string to the inner array.
                var complianceLevelsMap = new Map();
                complianceLevelsMap.set(complianceLevel, [tag]);

                // Add the compliance levels map to the metadata group map.
                metadataGroupsMap.set(metadataGroup, complianceLevelsMap);
            }
        }

        // Store required globals.
        storeData("_g", required);

        // Attach tags to the DOM.
        attachToDom(metadataGroupsMap);

        // Bind general metadata events.
        bindGeneralMetadataEvents()
    }

    /**
     *
     *
     * @param metadataGroupsMap   The map of tags organized by group.
     */
    function attachToDom(metadataGroupsMap) {

        // Sort the map.
        metadataGroupsMap = sortMapByKeys(metadataGroupsMap, "normal");

        // For each map key (group).
        for (var [metadataGroup, complianceLevelsMap] of metadataGroupsMap.entries()) {

            // Reverse sort the map.
            complianceLevelsMap = sortMapByKeys(complianceLevelsMap, "reverse");

            // Create a category title from the metadata group.
            var title = metadataGroup.replace(/_/g, ' ');
            if (title === "root") {
                title = "general";
            }
            // Capitalize first character.
            title = title.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
            $("#generalMetadataAssignment").append(
                "
\n" +
                "
" + title + "
\n" +
                "

\n" +
                "
\n"
            );

            for (const [complianceLevel, tags] of complianceLevelsMap.entries()) {
                var complianceLevelTitle = complianceLevel.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
                $("#generalMetadataAssignment #" + metadataGroup + " #"+ metadataGroup + "ToggleSection").append("
" + complianceLevelTitle + " Metadata:
");
                $("#generalMetadataAssignment #" + metadataGroup + " #"+ metadataGroup + "ToggleSection").append("

");
                 for (var i = 0; i < tags.length; i++) {
                    $("#generalMetadataAssignment #" + metadataGroup + " ul#" + complianceLevel).append(tags[i]);
                 }
            }
        }
        // Populate the tags with stored values.
        populateDataFromStorage();
    }

    /**
     * Sorts the provided map by keys according to the given sort order.
     *
     * @param map   The map to sort.
     * @param sortOrder  The order of the sort.
     * @returns {Map}   The sorted map.
     */
    function sortMapByKeys(map, sortOrder) {
        var keys = [];
        for (const [key, value] of map.entries()) {
            keys.push(key);
        }
        keys.sort();
        if (sortOrder === "reverse") {
            keys.reverse();
        }
        var sortedMap = new Map();
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            sortedMap.set(key, map.get(key));
        }
        return sortedMap;
    }

    /**
     * Binds focus out events for the input tags added to the DOM. Stores the entered values.
     */
    function bindGeneralMetadataEvents() {
        $("#generalMetadataAssignment input").focusout(function () {
            if ($(this).val().match(/\w+/)) {
                $(this).removeClass("required");
                storeGlobalMetadataEntry($(this).attr("id"), $(this).val());
                isComplete();
            }
        });
    }

    /**
     * Tests to see if all the required metadata has an entry.
     * Enables the next button if all required global metadata has been provided.
     */
    function isComplete() {
        if (testCompleteness()) {
            // Add stored global metadata info to input tag value.
            $("#globalMetadata").val(JSON.stringify(getStoredGlobalMetadata()));

            // remove disabled status for submit button.
            $("input[type=submit]#Next").removeAttr("disabled");
            // remove disabled class for submit button.
            $("input[type=submit]#Next").removeClass("disabled");
        }
    }

    /**
     * Compares the stored global metadata entries with the list of required entries.
     * Returns a boolean value based on whether all the required entries have been provided.
     *
     * @returns {boolean}   true if all required items are provided; otherwise false.
     */
    function testCompleteness() {
        var required = getStoredData("_g").split(/,/g);

        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();
        var stored = [];
        Object.keys(globalMetadata).forEach(function(key) {
            stored.push(key);
        });

        for (var i = 0; i < required.length; i++) {
            if (!stored.includes(required[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Populates the input tags with stored data.
     */
    function populateDataFromStorage() {
        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();
        Object.keys(globalMetadata).forEach(function(key) {
            var inputTag = $("#generalMetadataAssignment input#" + key);
            $(inputTag).val(globalMetadata[key]);
        });
        // Expand/collapse relevant categories.
        toggleCategories();
    }

    /**
     *
     */
    function toggleCategories() {
        // Check each input field.
        $("#generalMetadataAssignment input").each(function () {
            var inputTag = $(this);
            // Look at only the required tags.
            var ulTags = $(inputTag).parents("ul");
            if($(ulTags).attr("id") === "required") {
                // If the required input tag does not have a provided value.
                if (!$(inputTag).val().match(/\w+/)) {
                    // Find the toggle section div.
                    $(inputTag).parents("div").each(function () {
                        var parent = $(this);
                        if($(parent).attr("id").includes("ToggleSection")) {
                            // Expand the section that contains the required fields that need to be populated.
                            $(parent).removeClass("hideMe");
                            // Change the icon for the category header.
                            var categoryTitle = $(parent).prev("");
                            $(categoryTitle).removeClass("expand");
                            $(categoryTitle).addClass("collapse");
                            // Add required class to input tag.
                            $(inputTag).addClass("required");
                        }
                    });
                }
            }
        });
    }

    /**
     * Stores the provided key/value pair.
     *
     * @param key   The key of the entry to store.
     * @param value The value to store.
     */
    function storeGlobalMetadataEntry(key, value) {
        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();

        // Assign the provided object key to the provided value.
        globalMetadata[key] = value;

        // Update the stored global data.
        updateStoredGlobalMetadata(globalMetadata);
    }

    /**
     * Removes the entry corresponding to the provided key from storage.
     *
     * @param key   The key of the entry to remove.
     */
    function removeGlobaMetadataEntry(key) {
        // Get the stored global data.
        var globalMetadata =getStoredGlobalMetadata();

        // Delete the entry using the provided object key.
        delete globalMetadata[key];

        // Update the stored global data.
        updateStoredGlobalMetadata(globalMetadata);
    }

    /**
     * Retrieves the stored entry corresponding to the provided key.
     *
     * @param key    The key of the item to retrieve.
     * @returns {*}  The stored entry.
     */
   function getGlobalDataMetadataEntry(key) {
        // Get the stored global data.
        var globalMetadata = getStoredGlobalMetadata();

        return globalMetadata[key];
    }

    /**
     * Retrieves ALL stored global metadata entries.
     *
     * @returns {any} The global metadata.
     */
    function getStoredGlobalMetadata() {
        // Get the stored global data.
        var globalMetadata = getStoredData("globalMetadata");

        if (globalMetadata === null) {
            // This shouldn't happen; if we are here then something has gone very wrong (this info should be in the stored).
            displayErrorMessage("Unable to access stored variable matadata.");
        } else {
            // Un-stringify.
            return JSON.parse(globalMetadata);
        }
    }

    /**
     * Updated the stored global metadata with the provided object.
     *
     * @param globalMetadata The global metadata object.
     */
    function updateStoredGlobalMetadata(globalMetadata) {
        // Stringify and stored data.
        storeData("globalMetadata", JSON.stringify(globalMetadata));
    }

    // Expose these functions.
    return {
        populateTags: populateTags
    };

})();
<|endoftext|>


<commit_before>(function (angular) {

  'use strict';

  angular.module('bebop.notifications')

  .factory('notificationService', ['$q', 'authService', 'firebaseService', '$firebaseArray',

  function ($q, authService, firebaseService, $firebaseArray) {

    // Private

    var $notifications = [];

    var _TYPE = Object.freeze({
      REPLY: 0,
      TROPHY: 1
    });

    function init() {
      // Load-up notifications immediately
      authService.getUser().then(function ($user) {
        // Get unread notifications
        var $ref = firebaseService.getRef('notifications', $user.uid, 'items');
        return $firebaseArray($ref);
      }).then(function ($userNotifications) {
        $notifications = $userNotifications;
      }).catch(function(err) {
        console.error(err);
      });
    }

    function updateCount(userId) {
      return $q(function (resolve, reject) {
        var $ref = firebaseService.getRef('notifications', userId);
        // $ref.on('value', function ($snap) {
        //   var count = $snap.numChildren();

        // });
      });
    }

    init();

    // Public

    var _notificationService = {};

    function _notify(notificationType, userId, id) {

      return $q(function (resolve, reject) {
        // Todo lodash this beast, check for duplicates
        // Todo check if this is the same user

        // Get a handle on the user to be notified
        // var $notifications = firebaseService.getRef('notifications', userId);
        var $items = firebaseService.getRef('notifications', userId, 'items');
        // var $item = firebaseService.getRef('notifications', userId, 'items', id)

        // Note: this will always overwrite existing notifications (we want that)
        $items.child(id).set({
          'type': notificationType,
          'id': id
        });

        return $items.on('child_added', function ($snap) {
          return updateCount(userId);
        });

      });
    }

    // Effectively deletes a notification
    function _markRead(userId, id) {
      return $q(function (resolve, reject) {

        // Get a handle on the user to be notified
        var $ref = firebaseService.getRef('notifications', userId, id);

        $ref.remove();

        $ref.on('child_removed', function () {
          resolve();
        });
      });
    }

    _notificationService.TYPE = _TYPE;
    _notificationService.notify = _notify;
    _notificationService.read = _markRead;
    _notificationService.get = $notifications;

    return _notificationService;

  }]);

})(angular);<commit_msg>Update notification count<commit_after>(function (angular) {

  'use strict';

  angular.module('bebop.notifications')

  .factory('notificationService', ['$q', 'authService', 'firebaseService', '$firebaseArray',

  function ($q, authService, firebaseService, $firebaseArray) {

    // Private

    var $notifications = [];

    var _TYPE = Object.freeze({
      REPLY: 0,
      TROPHY: 1
    });

    function updateCount($event) {
      if ($event) {
        authService.getUser().then(function ($user) {
          var $ref = firebaseService.getRef('notifications', $user.uid);
          $ref.update({count: $notifications.length});
        }).catch(function(err) {
          console.error(err);
        });
      }
    }

    function init() {
      // Load-up notifications immediately
      authService.getUser().then(function ($user) {
        // Get unread notifications
        var $ref = firebaseService.getRef('notifications', $user.uid, 'items');
        return $firebaseArray($ref);
      }).then(function ($userNotifications) {
        $notifications = $userNotifications;
        $notifications.$watch(updateCount);
      }).catch(function(err) {
        console.error(err);
      });
    }

    init();

    // Public

    var _notificationService = {};

    function _notify(notificationType, userId, id) {

      return $q(function (resolve, reject) {
        // Todo check if this is the same user
        // Get a handle on the user to be notified
        var $items = firebaseService.getRef('notifications', userId, 'items');

        // Note: this will always overwrite existing notifications (we want that)
        $items.child(id).set({
          'type': notificationType,
          'id': id
        });

        return $items.on('child_added', function ($snap) {
          resolve();
        });

      });
    }

    // Effectively deletes a notification
    function _markRead(userId, id) {
      return $q(function (resolve, reject) {

        // Get a handle on the user to be notified
        var $ref = firebaseService.getRef('notifications', userId, id);

        $ref.remove();

        $ref.on('child_removed', function () {
          resolve();
        });
      });
    }

    _notificationService.TYPE = _TYPE;
    _notificationService.notify = _notify;
    _notificationService.read = _markRead;
    _notificationService.get = $notifications;

    return _notificationService;

  }]);

})(angular);<|endoftext|>


<commit_before>/*jshint unused:false*/
var chai = require('chai'),
    expect = chai.expect;
var request = require('supertest');

module.exports = function() {
  'use strict';

  this.Given(/^The Caddis server has started$/, function(callback) {
    request(this.serverLocation)
      .get('/')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function(error, res){
        expect(error ? false : true).to.equal(true, 'Failed to access server: ' + error);
        callback();
      });
  });

};<commit_msg>investigating double callback exception on travis.<commit_after>/*jshint unused:false*/
var chai = require('chai'),
    expect = chai.expect;
var request = require('supertest');

module.exports = function() {
  'use strict';

  this.Given(/^The Caddis server has started$/, function(callback) {
    request(this.serverLocation)
      .get('/')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function(error, res){
        if(error) {
          expect(error ? false : true).to.equal(true, 'Failed to access server: ' + error);
        }
        else {
          callback();
        }
      });
  });

};<|endoftext|>


<commit_before>$(function() {
    function PrinterStateViewModel(parameters) {
        var self = this;

        self.loginState = parameters[0];
        self.printerProfiles = parameters[1];

        self.stateString = ko.observable(undefined);
        self.isErrorOrClosed = ko.observable(undefined);
        self.isOperational = ko.observable(undefined);
        self.isPrinting = ko.observable(undefined);
        self.isHeating = ko.observable(undefined);
        self.isPaused = ko.observable(undefined);
        self.isError = ko.observable(undefined);
        self.isReady = ko.observable(undefined);
        self.isLoading = ko.observable(undefined);
        self.isSdReady = ko.observable(undefined);

        self.stateClass = ko.observable(undefined);
        self.isShutdown = ko.observable(undefined);

        self.enablePrint = ko.pureComputed(function() {
            return self.isOperational() && self.isReady() && !self.isPrinting() && self.loginState.isUser() && self.filename() != undefined;
        });
        self.enablePause = ko.pureComputed(function() {
            return self.isOperational() && (self.isPrinting() || self.isPaused()) && self.loginState.isUser();
        });
        self.enableCancel = ko.pureComputed(function() {
            return self.isOperational() && (self.isPrinting() || self.isPaused()) && self.loginState.isUser();
        });

        self.filename = ko.observable(undefined);
        self.progress = ko.observable(undefined);
        self.filesize = ko.observable(undefined);
        self.filepos = ko.observable(undefined);
        self.printTime = ko.observable(undefined);
        self.printTimeLeft = ko.observable(undefined);
        self.sd = ko.observable(undefined);
        self.timelapse = ko.observable(undefined);

        self.busyFiles = ko.observableArray([]);

        self.filament = ko.observableArray([]);
        self.estimatedPrintTime = ko.observable(undefined);
        self.lastPrintTime = ko.observable(undefined);

        self.currentHeight = ko.observable(undefined);

        self.TITLE_PRINT_BUTTON_PAUSED = gettext("Restarts the print job from the beginning");
        self.TITLE_PRINT_BUTTON_UNPAUSED = gettext("Starts the print job");
        self.TITLE_PAUSE_BUTTON_PAUSED = gettext("Resumes the print job");
        self.TITLE_PAUSE_BUTTON_UNPAUSED = gettext("Pauses the print job");

        self.titlePrintButton = ko.observable(self.TITLE_PRINT_BUTTON_UNPAUSED);
        self.titlePauseButton = ko.observable(self.TITLE_PAUSE_BUTTON_UNPAUSED);

        self.printerLogo = ko.computed(function() {
            var logo = "";

            if (self.isErrorOrClosed() !== undefined && !self.isErrorOrClosed() && !self.isError()) {
                var profile = self.printerProfiles.currentProfileData().id();
                if (profile == "_default") {
                    profile = "beethefirst";
                }
                logo = "/static/img/logo_" + profile + ".png";
            }

            return logo;
        });

        self.estimatedPrintTimeString = ko.pureComputed(function() {
            if (self.lastPrintTime())
                return formatDuration(self.lastPrintTime());
            if (self.estimatedPrintTime())
                return formatDuration(self.estimatedPrintTime());
            return "-";
        });
        self.byteString = ko.pureComputed(function() {
            if (!self.filesize())
                return "-";
            var filepos = self.filepos() ? formatSize(self.filepos()) : "-";
            return filepos + " / " + formatSize(self.filesize());
        });
        self.heightString = ko.pureComputed(function() {
            if (!self.currentHeight())
                return "-";
            return _.sprintf("%.02fmm", self.currentHeight());
        });
        self.printTimeString = ko.pureComputed(function() {
            if (!self.printTime())
                return "-";
            return formatDurationHoursMinutes(self.printTime());
        });
        self.printTimeLeftString = ko.pureComputed(function() {
            if (self.printTimeLeft() == undefined) {
                if (!self.printTime() || !(self.isPrinting() || self.isPaused())) {
                    return "-";
                } else {
                    return gettext("Calculating...");
                }
            } else {
                return formatFuzzyEstimation(self.printTimeLeft());
            }
        });
        self.progressString = ko.pureComputed(function() {
            if (!self.progress())
                return 0;
            return self.progress();
        });
        self.pauseString = ko.pureComputed(function() {
            if (self.isPaused())
                return gettext("Continue");
            else
                return gettext("Pause");
        });

        self.timelapseString = ko.pureComputed(function() {
            var timelapse = self.timelapse();

            if (!timelapse || !timelapse.hasOwnProperty("type"))
                return "-";

            var type = timelapse["type"];
            if (type == "zchange") {
                return gettext("On Z Change");
            } else if (type == "timed") {
                return gettext("Timed") + " (" + timelapse["options"]["interval"] + " " + gettext("sec") + ")";
            } else {
                return "-";
            }
        });

        self.fromCurrentData = function(data) {
            self._fromData(data);
        };

        self.fromHistoryData = function(data) {
            self._fromData(data);
        };

        self.fromTimelapseData = function(data) {
            self.timelapse(data);
        };

        self._proccessStateClass = function() {
            self.stateClass("text-black");

            if (self.isOperational()) {
                self.stateClass("text-success");
            }
            if (self.isPaused()) {
                self.stateClass("text-black");
            }
            if (self.isHeating()) {
                self.stateClass("text-error");
            }
            if (self.isPrinting()) {
                self.stateClass("text-primary");
            }
            if (self.isShutdown()) {
                self.stateClass("text-black");
            }
            if (self.isErrorOrClosed()) {
                self.stateClass("text-warning");
            }
        };

        self._fromData = function(data) {
            self._processStateData(data.state);
            self._processJobData(data.job);
            self._processProgressData(data.progress);
            self._processZData(data.currentZ);
            self._processBusyFiles(data.busyFiles);

            self._proccessStateClass();
        };

        self._processStateData = function(data) {
            var prevPaused = self.isPaused();

            self.stateString(gettext(data.text));
            self.isErrorOrClosed(data.flags.closedOrError);
            self.isOperational(data.flags.operational);
            self.isPaused(data.flags.paused);
            self.isPrinting(data.flags.printing);
            self.isError(data.flags.error);
            self.isReady(data.flags.ready);
            self.isSdReady(data.flags.sdReady);
            self.isHeating(data.flags.heating);
            self.isShutdown(data.flags.shutdown);

            if (self.isPaused() != prevPaused) {
                if (self.isPaused()) {
                    self.titlePrintButton(self.TITLE_PRINT_BUTTON_PAUSED);
                    self.titlePauseButton(self.TITLE_PAUSE_BUTTON_PAUSED);
                } else {
                    self.titlePrintButton(self.TITLE_PRINT_BUTTON_UNPAUSED);
                    self.titlePauseButton(self.TITLE_PAUSE_BUTTON_UNPAUSED);
                }
            }
        };

        self._processJobData = function(data) {
            if (data.file) {
                self.filename(data.file.name);
                self.filesize(data.file.size);
                self.sd(data.file.origin == "sdcard");
            } else {
                self.filename(undefined);
                self.filesize(undefined);
                self.sd(undefined);
            }

            self.estimatedPrintTime(data.estimatedPrintTime);
            self.lastPrintTime(data.lastPrintTime);

            var result = [];
            if (data.filament && typeof(data.filament) == "object" && _.keys(data.filament).length > 0) {
                for (var key in data.filament) {
                    if (!_.startsWith(key, "tool") || !data.filament[key] || !data.filament[key].hasOwnProperty("length") || data.filament[key].length <= 0) continue;

                    result.push({
                        name: ko.observable(gettext("Tool") + " " + key.substr("tool".length)),
                        data: ko.observable(data.filament[key])
                    });
                }
            }
            self.filament(result);
        };

        self._processProgressData = function(data) {
            if (data.completion) {
                self.progress(data.completion);
            } else {
                self.progress(undefined);
            }
            self.filepos(data.filepos);
            self.printTime(data.printTime);
            self.printTimeLeft(data.printTimeLeft);
        };

        self._processZData = function(data) {
            self.currentHeight(data);
        };

        self._processBusyFiles = function(data) {
            var busyFiles = [];
            _.each(data, function(entry) {
                if (entry.hasOwnProperty("name") && entry.hasOwnProperty("origin")) {
                    busyFiles.push(entry.origin + ":" + entry.name);
                }
            });
            self.busyFiles(busyFiles);
        };

        self.print = function() {
            var restartCommand = function() {
                self._jobCommand("restart");
            };

            if (self.isPaused()) {
                $("#confirmation_dialog .confirmation_dialog_message").text(gettext("This will restart the print job from the beginning."));
                $("#confirmation_dialog .confirmation_dialog_acknowledge").unbind("click");
                $("#confirmation_dialog .confirmation_dialog_acknowledge").click(function(e) {e.preventDefault(); $("#confirmation_dialog").modal("hide"); restartCommand(); });
                $("#confirmation_dialog").modal("show");
            } else {
                self._jobCommand("start");
            }
        };

        self.shutdown = function() {
            $('#job_shutdown').prop('disabled', true);

            self._jobCommand("shutdown", function () {
                $('#shutdown_confirmation').removeClass('hidden');
                $('#shutdown_panel').addClass('hidden');
            });
        };

        self.pause = function() {
            self._jobCommand("pause");

            self._restoreShutdown();
        };

        self._restoreShutdown = function() {
            $('#job_shutdown').prop('disabled', false);
            $('#shutdown_confirmation').addClass('hidden');
            $('#shutdown_panel').removeClass('hidden');
        }

        self.cancel = function() {
            $('#job_cancel').prop('disabled', true);
            self._restoreShutdown();

            self._jobCommand("cancel", function() {

                $('#job_cancel').prop('disabled', false);

                // Hides the status panel
                if ($("#state").hasClass('in')) {
                    $("#state").collapse("hide");
                }
            });
        };

        self._jobCommand = function(command, callback) {
            $.ajax({
                url: API_BASEURL + "job",
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=UTF-8",
                data: JSON.stringify({command: command}),
                success: function(response) {
                    if (callback != undefined) {
                        callback();
                    }
                }
            });
        };

        /**
         * This function shows the maintenance panel and
         * automatically displays the change filament dialog
         */
        self.showMaintenanceFilamentChange = function() {
            $('#navbar_show_maintenance').click();

        };
    }

    OCTOPRINT_VIEWMODELS.push([
        PrinterStateViewModel,
        ["loginStateViewModel", "printerProfilesViewModel"],
        ["#state_wrapper", "#drop_overlay"]
    ]);
});
<commit_msg>BEEWEB-76 Print panel must be disabled when heating<commit_after>$(function() {
    function PrinterStateViewModel(parameters) {
        var self = this;

        self.loginState = parameters[0];
        self.printerProfiles = parameters[1];

        self.stateString = ko.observable(undefined);
        self.isErrorOrClosed = ko.observable(undefined);
        self.isOperational = ko.observable(undefined);
        self.isPrinting = ko.observable(undefined);
        self.isHeating = ko.observable(undefined);
        self.isPaused = ko.observable(undefined);
        self.isError = ko.observable(undefined);
        self.isReady = ko.observable(undefined);
        self.isLoading = ko.observable(undefined);
        self.isSdReady = ko.observable(undefined);

        self.stateClass = ko.observable(undefined);
        self.isShutdown = ko.observable(undefined);

        self.enablePrint = ko.pureComputed(function() {
            return self.isOperational() && self.isReady() && !self.isPrinting() && !self.isHeating()
            && self.loginState.isUser() && self.filename() != undefined;
        });
        self.enablePause = ko.pureComputed(function() {
            return self.isOperational() && (self.isPrinting() || self.isPaused()) && self.loginState.isUser();
        });
        self.enableCancel = ko.pureComputed(function() {
            return self.isOperational() && (self.isPrinting() || self.isPaused()) && self.loginState.isUser();
        });

        self.filename = ko.observable(undefined);
        self.progress = ko.observable(undefined);
        self.filesize = ko.observable(undefined);
        self.filepos = ko.observable(undefined);
        self.printTime = ko.observable(undefined);
        self.printTimeLeft = ko.observable(undefined);
        self.sd = ko.observable(undefined);
        self.timelapse = ko.observable(undefined);

        self.busyFiles = ko.observableArray([]);

        self.filament = ko.observableArray([]);
        self.estimatedPrintTime = ko.observable(undefined);
        self.lastPrintTime = ko.observable(undefined);

        self.currentHeight = ko.observable(undefined);

        self.TITLE_PRINT_BUTTON_PAUSED = gettext("Restarts the print job from the beginning");
        self.TITLE_PRINT_BUTTON_UNPAUSED = gettext("Starts the print job");
        self.TITLE_PAUSE_BUTTON_PAUSED = gettext("Resumes the print job");
        self.TITLE_PAUSE_BUTTON_UNPAUSED = gettext("Pauses the print job");

        self.titlePrintButton = ko.observable(self.TITLE_PRINT_BUTTON_UNPAUSED);
        self.titlePauseButton = ko.observable(self.TITLE_PAUSE_BUTTON_UNPAUSED);

        self.printerLogo = ko.computed(function() {
            var logo = "";

            if (self.isErrorOrClosed() !== undefined && !self.isErrorOrClosed() && !self.isError()) {
                var profile = self.printerProfiles.currentProfileData().id();
                if (profile == "_default") {
                    profile = "beethefirst";
                }
                logo = "/static/img/logo_" + profile + ".png";
            }

            return logo;
        });

        self.estimatedPrintTimeString = ko.pureComputed(function() {
            if (self.lastPrintTime())
                return formatDuration(self.lastPrintTime());
            if (self.estimatedPrintTime())
                return formatDuration(self.estimatedPrintTime());
            return "-";
        });
        self.byteString = ko.pureComputed(function() {
            if (!self.filesize())
                return "-";
            var filepos = self.filepos() ? formatSize(self.filepos()) : "-";
            return filepos + " / " + formatSize(self.filesize());
        });
        self.heightString = ko.pureComputed(function() {
            if (!self.currentHeight())
                return "-";
            return _.sprintf("%.02fmm", self.currentHeight());
        });
        self.printTimeString = ko.pureComputed(function() {
            if (!self.printTime())
                return "-";
            return formatDurationHoursMinutes(self.printTime());
        });
        self.printTimeLeftString = ko.pureComputed(function() {
            if (self.printTimeLeft() == undefined) {
                if (!self.printTime() || !(self.isPrinting() || self.isPaused())) {
                    return "-";
                } else {
                    return gettext("Calculating...");
                }
            } else {
                return formatFuzzyEstimation(self.printTimeLeft());
            }
        });
        self.progressString = ko.pureComputed(function() {
            if (!self.progress())
                return 0;
            return self.progress();
        });
        self.pauseString = ko.pureComputed(function() {
            if (self.isPaused())
                return gettext("Continue");
            else
                return gettext("Pause");
        });

        self.timelapseString = ko.pureComputed(function() {
            var timelapse = self.timelapse();

            if (!timelapse || !timelapse.hasOwnProperty("type"))
                return "-";

            var type = timelapse["type"];
            if (type == "zchange") {
                return gettext("On Z Change");
            } else if (type == "timed") {
                return gettext("Timed") + " (" + timelapse["options"]["interval"] + " " + gettext("sec") + ")";
            } else {
                return "-";
            }
        });

        self.fromCurrentData = function(data) {
            self._fromData(data);
        };

        self.fromHistoryData = function(data) {
            self._fromData(data);
        };

        self.fromTimelapseData = function(data) {
            self.timelapse(data);
        };

        self._proccessStateClass = function() {
            self.stateClass("text-black");

            if (self.isOperational()) {
                self.stateClass("text-success");
            }
            if (self.isPaused()) {
                self.stateClass("text-black");
            }
            if (self.isHeating()) {
                self.stateClass("text-error");
            }
            if (self.isPrinting()) {
                self.stateClass("text-primary");
            }
            if (self.isShutdown()) {
                self.stateClass("text-black");
            }
            if (self.isErrorOrClosed()) {
                self.stateClass("text-warning");
            }
        };

        self._fromData = function(data) {
            self._processStateData(data.state);
            self._processJobData(data.job);
            self._processProgressData(data.progress);
            self._processZData(data.currentZ);
            self._processBusyFiles(data.busyFiles);

            self._proccessStateClass();
        };

        self._processStateData = function(data) {
            var prevPaused = self.isPaused();

            self.stateString(gettext(data.text));
            self.isErrorOrClosed(data.flags.closedOrError);
            self.isOperational(data.flags.operational);
            self.isPaused(data.flags.paused);
            self.isPrinting(data.flags.printing);
            self.isError(data.flags.error);
            self.isReady(data.flags.ready);
            self.isSdReady(data.flags.sdReady);
            self.isHeating(data.flags.heating);
            self.isShutdown(data.flags.shutdown);

            if (self.isPaused() != prevPaused) {
                if (self.isPaused()) {
                    self.titlePrintButton(self.TITLE_PRINT_BUTTON_PAUSED);
                    self.titlePauseButton(self.TITLE_PAUSE_BUTTON_PAUSED);
                } else {
                    self.titlePrintButton(self.TITLE_PRINT_BUTTON_UNPAUSED);
                    self.titlePauseButton(self.TITLE_PAUSE_BUTTON_UNPAUSED);
                }
            }
        };

        self._processJobData = function(data) {
            if (data.file) {
                self.filename(data.file.name);
                self.filesize(data.file.size);
                self.sd(data.file.origin == "sdcard");
            } else {
                self.filename(undefined);
                self.filesize(undefined);
                self.sd(undefined);
            }

            self.estimatedPrintTime(data.estimatedPrintTime);
            self.lastPrintTime(data.lastPrintTime);

            var result = [];
            if (data.filament && typeof(data.filament) == "object" && _.keys(data.filament).length > 0) {
                for (var key in data.filament) {
                    if (!_.startsWith(key, "tool") || !data.filament[key] || !data.filament[key].hasOwnProperty("length") || data.filament[key].length <= 0) continue;

                    result.push({
                        name: ko.observable(gettext("Tool") + " " + key.substr("tool".length)),
                        data: ko.observable(data.filament[key])
                    });
                }
            }
            self.filament(result);
        };

        self._processProgressData = function(data) {
            if (data.completion) {
                self.progress(data.completion);
            } else {
                self.progress(undefined);
            }
            self.filepos(data.filepos);
            self.printTime(data.printTime);
            self.printTimeLeft(data.printTimeLeft);
        };

        self._processZData = function(data) {
            self.currentHeight(data);
        };

        self._processBusyFiles = function(data) {
            var busyFiles = [];
            _.each(data, function(entry) {
                if (entry.hasOwnProperty("name") && entry.hasOwnProperty("origin")) {
                    busyFiles.push(entry.origin + ":" + entry.name);
                }
            });
            self.busyFiles(busyFiles);
        };

        self.print = function() {
            var restartCommand = function() {
                self._jobCommand("restart");
            };

            if (self.isPaused()) {
                $("#confirmation_dialog .confirmation_dialog_message").text(gettext("This will restart the print job from the beginning."));
                $("#confirmation_dialog .confirmation_dialog_acknowledge").unbind("click");
                $("#confirmation_dialog .confirmation_dialog_acknowledge").click(function(e) {e.preventDefault(); $("#confirmation_dialog").modal("hide"); restartCommand(); });
                $("#confirmation_dialog").modal("show");
            } else {
                self._jobCommand("start");
            }
        };

        self.shutdown = function() {
            $('#job_shutdown').prop('disabled', true);

            self._jobCommand("shutdown", function () {
                $('#shutdown_confirmation').removeClass('hidden');
                $('#shutdown_panel').addClass('hidden');
            });
        };

        self.pause = function() {
            self._jobCommand("pause");

            self._restoreShutdown();
        };

        self._restoreShutdown = function() {
            $('#job_shutdown').prop('disabled', false);
            $('#shutdown_confirmation').addClass('hidden');
            $('#shutdown_panel').removeClass('hidden');
        }

        self.cancel = function() {
            $('#job_cancel').prop('disabled', true);
            self._restoreShutdown();

            self._jobCommand("cancel", function() {

                $('#job_cancel').prop('disabled', false);

                // Hides the status panel
                if ($("#state").hasClass('in')) {
                    $("#state").collapse("hide");
                }
            });
        };

        self._jobCommand = function(command, callback) {
            $.ajax({
                url: API_BASEURL + "job",
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=UTF-8",
                data: JSON.stringify({command: command}),
                success: function(response) {
                    if (callback != undefined) {
                        callback();
                    }
                }
            });
        };

        /**
         * This function shows the maintenance panel and
         * automatically displays the change filament dialog
         */
        self.showMaintenanceFilamentChange = function() {
            $('#navbar_show_maintenance').click();

        };
    }

    OCTOPRINT_VIEWMODELS.push([
        PrinterStateViewModel,
        ["loginStateViewModel", "printerProfilesViewModel"],
        ["#state_wrapper", "#drop_overlay"]
    ]);
});
<|endoftext|>


<commit_before>import { useQuery } from '@apollo/react-hooks'
import Breadcrumbs from '@material-ui/core/Breadcrumbs'
import Grid from '@material-ui/core/Grid'
import { makeStyles } from '@material-ui/core/styles'
import NavigateNextIcon from '@material-ui/icons/NavigateNext'
import classnames from 'classnames'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState } from 'react'
import { Link, useLocation, useHistory } from 'react-router-dom'

import { TL1, TL2, Label3 } from 'src/components/typography'

import Cassettes from './MachineComponents/Cassettes'
import Commissions from './MachineComponents/Commissions'
import Details from './MachineComponents/Details'
import Overview from './MachineComponents/Overview'
import Transactions from './MachineComponents/Transactions'
import styles from './Machines.styles'
const useStyles = makeStyles(styles)

const GET_INFO = gql`
  query getMachine($deviceId: ID!, $billFilters: JSONObject) {
    machine(deviceId: $deviceId) {
      name
      deviceId
      paired
      lastPing
      pairedAt
      version
      model
      cashbox
      cassette1
      cassette2
      cassette3
      cassette4
      numberOfCassettes
      statuses {
        label
        type
      }
      downloadSpeed
      responseTime
      packetLoss
      latestEvent {
        note
      }
    }
    bills(filters: $billFilters) {
      id
      fiat
      deviceId
      created
    }
    config
  }
`

const getMachineID = path => path.slice(path.lastIndexOf('/') + 1)

const MachineRoute = () => {
  const location = useLocation()
  const history = useHistory()

  const id = getMachineID(location.pathname)

  const [loading, setLoading] = useState(true)

  const { data, refetch } = useQuery(GET_INFO, {
    onCompleted: data => {
      if (data.machine === null)
        return history.push('/maintenance/machine-status')

      setLoading(false)
    },
    variables: {
      deviceId: id
    },
    billFilters: {
      deviceId: id,
      batch: 'none'
    }
  })

  const reload = () => {
    return history.push(location.pathname)
  }

  return (
    !loading && (
      <Machines data={data} refetch={refetch} reload={reload}></Machines>
    )
  )
}

const Machines = ({ data, refetch, reload }) => {
  const classes = useStyles()

  const timezone = R.path(['config', 'locale_timezone'], data) ?? {}

  const machine = R.path(['machine'])(data) ?? {}
  const config = R.path(['config'])(data) ?? {}
  const bills = R.path(['bills'])(data) ?? []

  const machineName = R.path(['name'])(machine) ?? null
  const machineID = R.path(['deviceId'])(machine) ?? null

  return (
    <Grid container className={classes.grid}>
      <Grid item xs={3}>
        <Grid item xs={12}>

            <Breadcrumbs separator={<NavigateNextIcon fontSize="small" />}>
              <Link to="/dashboard" className={classes.breadcrumbLink}>
                <Label3 noMargin className={classes.subtitle}>
                  Dashboard
                </Label3>
              </Link>
              <TL2 noMargin className={classes.subtitle}>
                {machineName}
              </TL2>
            </Breadcrumbs>
            <Overview data={machine} onActionSuccess={reload} />

        </Grid>
      </Grid>
      <Grid item xs={9}>

            <TL1 className={classes.subtitle}>{'Details'}</TL1>

            <TL1 className={classes.subtitle}>{'Cash box & cassettes'}</TL1>
            <Cassettes
              refetchData={refetch}
              machine={machine}
              config={config ?? false}
              bills={bills}
            />

            <TL1 className={classes.subtitle}>{'Latest transactions'}</TL1>
            <Transactions id={machineID} />

            <TL1 className={classes.subtitle}>{'Commissions'}</TL1>
            <Commissions name={'commissions'} id={machineID} />

      </Grid>
    </Grid>
  )
}

export default MachineRoute
<commit_msg>fix: redirect user on machine unpair<commit_after>import { useQuery } from '@apollo/react-hooks'
import Breadcrumbs from '@material-ui/core/Breadcrumbs'
import Grid from '@material-ui/core/Grid'
import { makeStyles } from '@material-ui/core/styles'
import NavigateNextIcon from '@material-ui/icons/NavigateNext'
import classnames from 'classnames'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState } from 'react'
import { Link, useLocation, useHistory } from 'react-router-dom'

import { TL1, TL2, Label3 } from 'src/components/typography'

import Cassettes from './MachineComponents/Cassettes'
import Commissions from './MachineComponents/Commissions'
import Details from './MachineComponents/Details'
import Overview from './MachineComponents/Overview'
import Transactions from './MachineComponents/Transactions'
import styles from './Machines.styles'
const useStyles = makeStyles(styles)

const GET_INFO = gql`
  query getMachine($deviceId: ID!, $billFilters: JSONObject) {
    machine(deviceId: $deviceId) {
      name
      deviceId
      paired
      lastPing
      pairedAt
      version
      model
      cashbox
      cassette1
      cassette2
      cassette3
      cassette4
      numberOfCassettes
      statuses {
        label
        type
      }
      downloadSpeed
      responseTime
      packetLoss
      latestEvent {
        note
      }
    }
    bills(filters: $billFilters) {
      id
      fiat
      deviceId
      created
    }
    config
  }
`

const GET_MACHINES = gql`
  {
    machines {
      name
      deviceId
    }
  }
`

const getMachineID = path => path.slice(path.lastIndexOf('/') + 1)

const MachineRoute = () => {
  const location = useLocation()
  const history = useHistory()

  const id = getMachineID(location.pathname)

  const [loading, setLoading] = useState(true)

  const { data, refetch } = useQuery(GET_INFO, {
    onCompleted: data => {
      if (data.machine === null)
        return history.push('/maintenance/machine-status')

      setLoading(false)
    },
    variables: {
      deviceId: id
    },
    billFilters: {
      deviceId: id,
      batch: 'none'
    }
  })

  const reload = () => {
    return history.push(location.pathname)
  }

  return (
    !loading && (
      <Machines data={data} refetch={refetch} reload={reload}></Machines>
    )
  )
}

const Machines = ({ data, refetch, reload }) => {
  const classes = useStyles()

  const timezone = R.path(['config', 'locale_timezone'], data) ?? {}

  const machine = R.path(['machine'])(data) ?? {}
  const config = R.path(['config'])(data) ?? {}
  const bills = R.path(['bills'])(data) ?? []

  const machineName = R.path(['name'])(machine) ?? null
  const machineID = R.path(['deviceId'])(machine) ?? null

  return (
    <Grid container className={classes.grid}>
      <Grid item xs={3}>
        <Grid item xs={12}>

            <Breadcrumbs separator={<NavigateNextIcon fontSize="small" />}>
              <Link to="/dashboard" className={classes.breadcrumbLink}>
                <Label3 noMargin className={classes.subtitle}>
                  Dashboard
                </Label3>
              </Link>
              <TL2 noMargin className={classes.subtitle}>
                {machineName}
              </TL2>
            </Breadcrumbs>
            <Overview data={machine} onActionSuccess={reload} />

        </Grid>
      </Grid>
      <Grid item xs={9}>

            <TL1 className={classes.subtitle}>{'Details'}</TL1>

            <TL1 className={classes.subtitle}>{'Cash box & cassettes'}</TL1>
            <Cassettes
              refetchData={refetch}
              machine={machine}
              config={config ?? false}
              bills={bills}
            />

            <TL1 className={classes.subtitle}>{'Latest transactions'}</TL1>
            <Transactions id={machineID} />

            <TL1 className={classes.subtitle}>{'Commissions'}</TL1>
            <Commissions name={'commissions'} id={machineID} />

      </Grid>
    </Grid>
  )
}

export default MachineRoute
<|endoftext|>