import utils = require("../common/utils"); import styles = require("./styles/styles"); import React = require("react"); import ReactDOMServer = require("react-dom/server"); import * as csx from './base/csx'; import {BaseComponent} from "./ui"; import * as ui from "./ui"; import {cast,server} from "../socket/socketClient"; import * as commands from "./commands/commands"; import * as types from "../common/types"; import {AvailableProjectConfig} from "../common/types"; import {Clipboard} from "./components/clipboard"; import {PendingRequestsIndicator} from "./pendingRequestsIndicator"; import {Icon} from "./components/icon"; import {tabState,tabStateChanged} from "./tabs/v2/appTabsContainer"; import {Progress} from "./components/progress"; import {connect} from "react-redux"; import {StoreState,expandErrors,collapseErrors} from "./state/state"; import * as state from "./state/state"; import {errorsCache} from "./globalErrorCacheClient"; import {testResultsCache} from "./clientTestResultsCache"; let notificationKeyboardStyle = { border: '2px solid', borderRadius: '6px', display: 'inline-block', padding: '5px', background: 'grey', } const ouputStatusStyle = csx.extend(styles.noSelect, {fontSize:'.6rem'}); const activeProjectContainerStyle = csx.extend( styles.statusBarSection, styles.hand, styles.noSelect, { border: '1px solid grey', paddingTop: '2px', paddingBottom: '2px', paddingLeft: '4px', paddingRight: '4px', fontSize: '.7rem', marginTop: '1px', } ); export interface Props { // from react-redux ... connected below errorsExpanded?: boolean; activeProject?: AvailableProjectConfig; activeProjectFiles?: { [filePath: string]: boolean }; socketConnected?: boolean; outputStatusCache?: types.JSOutputStatusCache; liveBuildResults?: types.LiveBuildResults; fileTreeShown?: boolean; errorsDisplayMode?: types.ErrorsDisplayMode; errorsFilter?: string; tsWorking?: types.Working; testedWorking?: types.Working; } export interface State { } const projectTipKeboard = ReactDOMServer.renderToString(
Alt+Shift+P
); /** * The singleton status bar */ export var statusBar: StatusBar; @connect((state: StoreState): Props => { return { errorsExpanded: state.errorsExpanded, activeProject: state.activeProject, activeProjectFiles: state.activeProjectFilePathTruthTable, socketConnected: state.socketConnected, outputStatusCache: state.outputStatusCache, liveBuildResults: state.liveBuildResults, fileTreeShown: state.fileTreeShown, errorsDisplayMode: state.errorsDisplayMode, errorsFilter: state.errorsFilter, tsWorking: state.tsWorking, testedWorking: state.testedWorking, }; }) export class StatusBar extends BaseComponent{ constructor(props:Props){ super(props); this.state = { } } componentDidMount() { statusBar = this; tabStateChanged.on(()=>this.forceUpdate()); errorsCache.errorsDelta.on(() => this.forceUpdate()); testResultsCache.testResultsDelta.on(() => this.forceUpdate()); } render() { let tab = tabState.getSelectedTab(); let filePath = tab && utils.getFilePathFromUrl(tab.url); let protocol = tab && utils.getFilePathAndProtocolFromUrl(tab.url).protocol; const activeProjectDetails = this.props.activeProject ?{ this.openFile(this.props.activeProject.tsconfigFilePath); ui.notifyInfoNormalDisappear(`TIP : You can change the active project using project search

${projectTipKeboard}`, { onClick: () => commands.omniSelectProject.emit({}) }); }}> {this.props.activeProject.isVirtual && } {this.props.activeProject.name}
: ui.notifyWarningNormalDisappear(`There is no active project. Please select from the available ones

${projectTipKeboard}`, { onClick: () => commands.omniSelectProject.emit({}) }) } data-hint="There is no active TypeScript project. Robots deactivated.">
; let inActiveProjectSection = !tab ? '' : {state.inActiveProjectUrl(tab.url) ?ui.notifySuccessNormalDisappear(`The file is a part of the currently active TypeScript project and we are actively providing code intelligence`)} data-hint="File is part of the currently active project. 💻 providing code intelligence."> : ui.notifyWarningNormalDisappear(`The file is not a part of the currently active TypeScript project

${projectTipKeboard}`, { onClick: () => commands.omniSelectProject.emit({}) }) } data-hint="File is not a part of the currently active project. Robots deactivated.">
}
; const fileOutput = protocol !== 'file' ? null : !this.props.outputStatusCache[filePath] ? null : this.props.outputStatusCache[filePath] const fileOutputState = fileOutput && fileOutput.state; const openOutputJSFile = () => { commands.doToggleFileTab.emit({ filePath: fileOutput.outputFilePath }); } const fileOutputStateRendered = !!fileOutputState && { fileOutputState === types.JSOutputState.NoJSFile ? null : fileOutputState === types.JSOutputState.JSOutOfDate ? ❌ JS Outdated : ✓ JS Current } ; const fileTreeToggleRendered = ; const updateRendered = serverState.update && ; const errorsUpdate = errorsCache.getErrorsLimited(); const errorFilteringActive = this.props.errorsDisplayMode !== types.ErrorsDisplayMode.all || this.props.errorsFilter.trim(); const errorsFilteredCount = tabState.errorsByFilePathFiltered().errorsFlattened.length; /** Tested */ const testResultsStats = testResultsCache.getStats(); const failing = !!testResultsStats.failCount; const totalThatRan = testResultsStats.passCount + testResultsStats.failCount; const testStatsRendered = !!testResultsStats.testCount && { commands.doOpenTestResultsView.emit({}); }}> { failing ? {testResultsStats.failCount}/{totalThatRan} fail : {testResultsStats.passCount}/{totalThatRan} pass } return (
{/* Left sections */} {errorsUpdate.totalCount} {errorFilteringActive && ' '} {errorFilteringActive && ( {errorsFilteredCount} )} {testStatsRendered} {fileTreeToggleRendered} {activeProjectDetails} {inActiveProjectSection} {filePath ?ui.notifyInfoQuickDisappear("File path copied to clipboard")} style={csx.extend(styles.statusBarSection,styles.noSelect,styles.hand)}> {filePath} :''} {fileOutputStateRendered} {/* seperator */} {/* Right sections */} { this.props.liveBuildResults.builtCount !== this.props.liveBuildResults.totalCount && {this.props.liveBuildResults.builtCount} / {this.props.liveBuildResults.totalCount} } {this.props.socketConnected? ui.notifySuccessNormalDisappear("Connected to alm server")}/> : ui.notifyWarningNormalDisappear("Disconneted from alm server")}/>} 🌟 🌹 {updateRendered}
); } toggleErrors = () => { if (this.props.errorsExpanded){ collapseErrors({}); } else{ expandErrors({}); } } toggleFileTree = () => { if (this.props.fileTreeShown) { state.collapseFileTree({}); } else { state.expandFileTree({}); } } openErrorLocation = (error: types.CodeError) => { commands.doOpenOrFocusFile.emit({ filePath: error.filePath, position: error.from }); } openFile = (filePath: string) => { commands.doOpenOrFocusFile.emit({ filePath }); } giveStar = () => { window.open('https://github.com/alm-tools/alm') } giveRose = () => { window.open('https://twitter.com/basarat') } whatsNew = () => { /** We currently show the diff. Once we have semantic releases we will show release notes */ const update = serverState.update; window.open(`https://github.com/alm-tools/alm/compare/v${update.current}...v${update.latest}`); } }