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.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}`);
}
}