Source: @@components/menu/menu.js

/**
 * @file Menu bar specification
 * @module @@components/menu/menu
 */
import React from 'react';
import {connect} from 'react-redux';
import { Avatar, Menu, Input, Affix, Button, Space } from 'antd';
import {
  UserOutlined,
  ShareAltOutlined,
  CloudUploadOutlined,
  DesktopOutlined,
  PlaySquareOutlined
} from '@ant-design/icons';
import { getAvatar, getSessionValid, getModelFileLocation, getFilename, getDirty } from '@@selectors';
import { openShareModal } from '@@components/menu/share-menu';
import { openSaveDialogModal } from '@@components/controls/file-dialog';
import { loginToSolid, logoutSolid } from '@@actions/solid/auth';
import { dispatchSet } from '@@app-state';
import * as ModelState from '@@app-state/model/state';
import styled from '@emotion/styled';
import { openSettingsModal } from '@@components/controls/settings';
import { FileMenu } from '@@components/menu/file-menu';
import { translated } from '@@localization';
import { saveData } from '@@actions/save';
import { openYasguiModal } from '@@components/Yasgui';

const FilenameInput = styled(Input)`
  border: none;
  font-size: 16px;
  max-width: 512px;
`;

const HiddenSpan = styled.span`
  font-size: 16px;
  position: absolute;
  top: -100px
`;

const getSaveIcons = (modelFileLocation, isDirty) => {
  const localProps = isDirty ? {color: 'orange', text: translated('Changes not saved')} : {color: 'green', text: translated('Changes saved')};
  const cloudProps = isDirty ? {color: 'orange', text: translated('Latest changes not saved to {modelFileLocation}', {modelFileLocation})} : {color: 'green', text: translated('File saved at {modelFileLocation}', {modelFileLocation})};

  return <div style={{display: 'flex', alignItems: 'center'}} onClick={saveData}>
    {!modelFileLocation && <DesktopOutlined style={{color: localProps.color, fontSize: 16}}/>}
    {!modelFileLocation && localProps.text}
    {modelFileLocation && <CloudUploadOutlined onClick={openSaveDialogModal} style={{color: cloudProps.color, fontSize: 16}}/>}
    {modelFileLocation && cloudProps.text}
  </div>
};

const iconStyle = {height: 48, width: 48};

class MenuComponent extends React.Component {
  state = {
    inputWidth: 0
  };

  constructor() {
    super();
    this.hiddenTitleRef = React.createRef();
  }

  componentDidMount() {
    this.setState({
      inputWidth: this.hiddenTitleRef.current.offsetWidth + 24 + 'px'
    })
  }

  render() {
    const {avatar, loggedIn, modelFileLocation, isDirty, filename} = this.props;

    return <Affix>
      <Menu selectable={false} mode="horizontal" style={{marginTop: -8, paddingLeft: 8}}>
        <Menu.Item style={{marginLeft: 4, padding: 0, marginBottom: -8, border: 'none'}}>
          <Space>
            <HiddenSpan ref={this.hiddenTitleRef}>{filename}</HiddenSpan>
            <FilenameInput style={{width: this.state.inputWidth}} value={filename} onPressEnter={e => e.target.blur()} onChange={e => {
              this.hiddenTitleRef.current.textContent = e.target.value;
              e.target.style.width = this.hiddenTitleRef.current.offsetWidth + 24 + 'px';
              dispatchProps.updateFilename(e.target.value)
            }}/>
            {getSaveIcons(modelFileLocation, isDirty)}
          </Space>
        </Menu.Item>
        <br/>
        {FileMenu({modelFileLocation, loggedIn})}
        <Menu.Item title={translated('Settings')} onClick={openSettingsModal}>{translated('Settings')}</Menu.Item>
        <Menu.SubMenu style={{height: 64, width: 64, position: 'absolute', top: 8, right: 0}}
                      icon={<Avatar style={iconStyle} size="large" src={avatar}
                                    icon={<UserOutlined style={iconStyle}/>}/>}>
          {
            loggedIn ? <Menu.Item onClick={logoutSolid}>{translated('Logout')}</Menu.Item> :
              <Menu.Item onClick={loginToSolid}>{translated('Login')}</Menu.Item>
          }
        </Menu.SubMenu>
        <Menu.Item style={{position: 'absolute', top: 12, right: 84}}><Button onClick={openShareModal}
                                                                              type="primary"><ShareAltOutlined/>{translated('Share')}</Button></Menu.Item>
        <Menu.Item style={{position: 'absolute', top: 12, right: 176}}><Button
          onClick={() => openYasguiModal({runQuery: true})} type="primary"><PlaySquareOutlined/>{translated('Run SPARQL Query')}</Button></Menu.Item>
      </Menu>
    </Affix>;
  }
}

const mapStateToProps = appState => ({
  avatar: getAvatar(appState),
  loggedIn: getSessionValid(appState),
  modelFileLocation: getModelFileLocation(appState),
  filename: getFilename(appState),
  isDirty: getDirty(appState)
});

const dispatchProps = {
  updateFilename: dispatchSet(ModelState.filename)
};

const connected = connect(mapStateToProps, null)(MenuComponent);
export { connected as Menu };