style: enforce LF linebreak and fix existing files (#15)

This commit is contained in:
kunzheng 2020-02-09 11:33:52 -08:00 коммит произвёл GitHub
Родитель b11e08304e
Коммит ade7902b47
15 изменённых файлов: 1422 добавлений и 1420 удалений

Просмотреть файл

@ -50,7 +50,8 @@
"react-start": "react-scripts start",
"test": "react-scripts test --env=jsdom --silent",
"eject": "react-scripts eject",
"tslint": "./node_modules/.bin/tslint 'src/**/*.ts*'"
"tslint": "./node_modules/.bin/tslint 'src/**/*.ts*'",
"tslintfix": "./node_modules/.bin/tslint 'src/**/*.ts*' --fix"
},
"eslintConfig": {
"extends": "react-app"

Просмотреть файл

@ -1,37 +1,37 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import React from "react";
import App from "./App";
import { Provider } from "react-redux";
import createReduxStore from "./redux/store/store";
import initialState from "./redux/store/initialState";
import { IApplicationState } from "./models//applicationState";
import { mount } from "enzyme";
import { Router } from "react-router-dom";
import { KeyboardManager } from "./react/components/common/keyboardManager/keyboardManager";
import { ErrorHandler } from "./react/components/common/errorHandler/errorHandler";
describe("App Component", () => {
const defaultState: IApplicationState = initialState;
const store = createReduxStore(defaultState);
function createComponent() {
return mount(
<Provider store={store}>
<App />
</Provider>,
);
}
it("renders without crashing", () => {
createComponent();
});
it("renders required top level components", () => {
const wrapper = createComponent();
expect(wrapper.find(Router).exists()).toBe(true);
expect(wrapper.find(KeyboardManager).exists()).toEqual(true);
expect(wrapper.find(ErrorHandler).exists()).toEqual(true);
});
});
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import React from "react";
import App from "./App";
import { Provider } from "react-redux";
import createReduxStore from "./redux/store/store";
import initialState from "./redux/store/initialState";
import { IApplicationState } from "./models//applicationState";
import { mount } from "enzyme";
import { Router } from "react-router-dom";
import { KeyboardManager } from "./react/components/common/keyboardManager/keyboardManager";
import { ErrorHandler } from "./react/components/common/errorHandler/errorHandler";
describe("App Component", () => {
const defaultState: IApplicationState = initialState;
const store = createReduxStore(defaultState);
function createComponent() {
return mount(
<Provider store={store}>
<App />
</Provider>,
);
}
it("renders without crashing", () => {
createComponent();
});
it("renders required top level components", () => {
const wrapper = createComponent();
expect(wrapper.find(Router).exists()).toBe(true);
expect(wrapper.find(KeyboardManager).exists()).toEqual(true);
expect(wrapper.find(ErrorHandler).exists()).toEqual(true);
});
});

Просмотреть файл

@ -1,25 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* Constants used throughout application
*/
export const constants = {
version: "pubpreview_1.0",
projectFormTempKey: "projectForm",
projectFileExtension: ".vott",
labelFileExtension: ".labels.json",
ocrFileExtension: ".ocr.json",
fieldsFileName: "fields.json",
maxConcurrentServiceRequests: 3,
statusCodeSucceeded: "succeeded",
statusCodeFailed: "failed",
apiKeyHeader: "Ocp-Apim-Subscription-Key",
maxRetry: 8,
initialRetryInterval: 500, // ms
convertedImageFormat: "image/jpeg",
convertedImageQuality: 0.7,
convertedThumbnailQuality: 0.2,
apiModelsPath: "/formrecognizer/v2.0-preview/custom/models",
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* Constants used throughout application
*/
export const constants = {
version: "pubpreview_1.0",
projectFormTempKey: "projectForm",
projectFileExtension: ".vott",
labelFileExtension: ".labels.json",
ocrFileExtension: ".ocr.json",
fieldsFileName: "fields.json",
maxConcurrentServiceRequests: 3,
statusCodeSucceeded: "succeeded",
statusCodeFailed: "failed",
apiKeyHeader: "Ocp-Apim-Subscription-Key",
maxRetry: 8,
initialRetryInterval: 500, // ms
convertedImageFormat: "image/jpeg",
convertedImageQuality: 0.7,
convertedThumbnailQuality: 0.2,
apiModelsPath: "/formrecognizer/v2.0-preview/custom/models",
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
export class AzureBlobStorageError extends Error {
public statusCode: number;
constructor(statusCode: number) {
super();
this.statusCode = statusCode;
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
export class AzureBlobStorageError extends Error {
public statusCode: number;
constructor(statusCode: number) {
super();
this.statusCode = statusCode;
}
}

2
src/react-app-env.d.ts поставляемый
Просмотреть файл

@ -1 +1 @@
/// <reference types="react-scripts" />
/// <reference types="react-scripts" />

Просмотреть файл

@ -1,313 +1,313 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Feature, MapBrowserEvent, View } from "ol";
import { Extent, getCenter } from "ol/extent";
import { defaults as defaultInteractions, DragPan, DragRotateAndZoom, Interaction } from "ol/interaction.js";
import ImageLayer from "ol/layer/Image";
import Layer from "ol/layer/Layer";
import VectorLayer from "ol/layer/Vector";
import Map from "ol/Map";
import Projection from "ol/proj/Projection";
import Static from "ol/source/ImageStatic.js";
import VectorSource from "ol/source/Vector";
import * as React from "react";
import "./styles.css";
import Utils from "./utils";
interface IImageMapProps {
imageUri: string;
imageWidth: number;
imageHeight: number;
imageAngle?: number;
featureStyler?: any;
enableFeatureSelection?: boolean;
handleFeatureSelect?: (feature: any, isTaggle: boolean) => void;
onMapReady: () => void;
}
export class ImageMap extends React.Component<IImageMapProps> {
private map: Map;
private imageLayer: ImageLayer;
private vectorLayer: VectorLayer;
private mapElement: HTMLDivElement | null = null;
private imageExtent: number[];
private countPointerDown: number = 0;
private isSwiping: boolean = false;
private readonly VECTOR_LAYER_NAME = "vectorLayer";
private ignorePointerMoveEventCount: number = 5;
private pointerMoveEventCount: number = 0;
private vectorLayerFilter = {
layerFilter: (layer: Layer) => layer.get("name") === this.VECTOR_LAYER_NAME,
};
constructor(props: IImageMapProps) {
super(props);
this.imageExtent = [0, 0, this.props.imageWidth, this.props.imageHeight];
}
public componentDidMount() {
this.initMap();
}
public componentDidUpdate(prevProps: IImageMapProps) {
if (prevProps.imageUri !== this.props.imageUri) {
this.imageExtent = [0, 0, this.props.imageWidth, this.props.imageHeight];
this.setImage(this.props.imageUri, this.imageExtent);
}
}
public render() {
return (
<div className="map-wrapper">
<div id="map" className="map" ref={(el) => this.mapElement = el}></div>
</div>
);
}
/**
* Add one feature to the map
*/
public addFeature = (feature: Feature) => {
this.vectorLayer.getSource().addFeature(feature);
}
/**
* Add features to the map
*/
public addFeatures = (features: Feature[]) => {
this.vectorLayer.getSource().addFeatures(features);
}
/**
* Add interaction to the map
*/
public addInteraction = (interaction: Interaction) => {
this.map.addInteraction(interaction);
}
/**
* Get all features from the map
*/
public getAllFeatures = () => {
return this.vectorLayer.getSource().getFeatures();
}
/**
* Remove specific feature object from the map
*/
public removeFeature = (feature: Feature) => {
this.vectorLayer.getSource().removeFeature(feature);
}
/**
* Remove all features from the map
*/
public removeAllFeatures = () => {
this.vectorLayer.getSource().clear();
}
/**
* Remove interaction from the map
*/
public removeInteraction = (interaction: Interaction) => {
this.map.removeInteraction(interaction);
}
/**
* Get the image extent (left, top, right, bottom)
*/
public getImageExtent = () => {
return this.imageExtent;
}
/**
* Get features at specific extend
*/
public getFeaturesInExtent = (extent: Extent): Feature[] => {
const features: Feature[] = [];
this.vectorLayer.getSource().forEachFeatureInExtent(extent, (feature) => {
features.push(feature);
});
return features;
}
private initMap = () => {
const projection = this.createProjection(this.imageExtent);
this.imageLayer = new ImageLayer({
source: this.createImageSource(this.props.imageUri, projection, this.imageExtent),
});
const options: any = {};
options.name = this.VECTOR_LAYER_NAME;
options.style = this.props.featureStyler;
options.source = new VectorSource();
this.vectorLayer = new VectorLayer(options);
this.map = new Map({
interactions: defaultInteractions({ doubleClickZoom: false }).extend([new DragRotateAndZoom()]),
target: "map",
layers: [this.imageLayer, this.vectorLayer],
view: this.createMapView(projection, this.imageExtent),
});
this.map.on("pointerdown", this.handlePointerDown);
this.map.on("pointermove", this.handlePointerMove);
this.map.on("pointerup", this.handlePointerUp);
}
private setImage = (imageUri: string, imageExtent: number[]) => {
const projection = this.createProjection(imageExtent);
this.imageLayer.setSource(this.createImageSource(imageUri, projection, imageExtent));
const mapView = this.createMapView(projection, imageExtent);
this.map.setView(mapView);
}
private createProjection = (imageExtend: number[]) => {
return new Projection({
code: "xkcd-image",
units: "pixels",
extent: imageExtend,
});
}
private createMapView = (projection: Projection, imageExtend: number[]) => {
const minZoom = this.getMinimumZoom();
const rotation = (this.props.imageAngle)
? Utils.degreeToRadians((this.props.imageAngle + 360) % 360)
: 0;
return new View({
projection,
center: getCenter(imageExtend),
rotation,
zoom: minZoom,
minZoom,
});
}
private createImageSource = (imageUri: string, projection: Projection, imageExtend: number[]) => {
return new Static({
url: imageUri,
projection,
imageExtent: imageExtend,
});
}
private getMinimumZoom = () => {
// In openlayers, the image will be projected into 256x256 pixels,
// and image will be 2x larger at each zoom level.
// https://openlayers.org/en/latest/examples/min-zoom.html
const containerAspectRatio = (this.mapElement)
? (this.mapElement.clientHeight / this.mapElement.clientWidth) : 1;
const imageAspectRatio = this.props.imageHeight / this.props.imageWidth;
if (imageAspectRatio > containerAspectRatio) {
// Fit to width
return Math.LOG2E * Math.log(this.mapElement!.clientHeight / 256);
} else {
// Fit to height
return Math.LOG2E * Math.log(this.mapElement!.clientWidth / 256);
}
}
private handlePointerDown = (event: MapBrowserEvent) => {
if (!this.props.enableFeatureSelection) {
return;
}
this.countPointerDown += 1;
if (this.countPointerDown >= 2) {
this.setDragPanInteraction(true /*dragPanEnabled*/);
this.isSwiping = false;
return;
}
const isPointerOnFeature = this.map.hasFeatureAtPixel(
this.map.getEventPixel(event.originalEvent),
this.vectorLayerFilter);
if (isPointerOnFeature && this.props.handleFeatureSelect) {
const eventPixel = this.map.getEventPixel(event.originalEvent);
this.map.forEachFeatureAtPixel(
eventPixel,
(feature) => {
if (this.props.handleFeatureSelect) {
this.props.handleFeatureSelect(feature, true /*isTaggle*/);
}
},
this.vectorLayerFilter);
}
this.setDragPanInteraction(!isPointerOnFeature /*dragPanEnabled*/);
this.isSwiping = isPointerOnFeature;
}
private handlePointerMove = (event: MapBrowserEvent) => {
if (this.shouldIgnorePointerMove()) {
return;
}
// disable vertical scrolling for iOS Safari
event.preventDefault();
const eventPixel = this.map.getEventPixel(event.originalEvent);
this.map.forEachFeatureAtPixel(
eventPixel,
(feature) => {
if (this.props.handleFeatureSelect) {
this.props.handleFeatureSelect(feature, false /*isTaggle*/);
}
},
this.vectorLayerFilter);
}
private handlePointerUp = () => {
if (!this.props.enableFeatureSelection) {
return;
}
this.countPointerDown -= 1;
if (this.countPointerDown === 0) {
this.setDragPanInteraction(true /*dragPanEnabled*/);
this.isSwiping = false;
this.pointerMoveEventCount = 0;
}
}
private setDragPanInteraction = (dragPanEnabled: boolean) => {
this.map.getInteractions().forEach((interaction) => {
if (interaction instanceof DragPan) {
interaction.setActive(dragPanEnabled);
}
});
}
private shouldIgnorePointerMove = () => {
if (!this.props.enableFeatureSelection) {
return true;
}
if (!this.isSwiping) {
return true;
}
if (this.ignorePointerMoveEventCount > this.pointerMoveEventCount) {
++this.pointerMoveEventCount;
return true;
}
return false;
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Feature, MapBrowserEvent, View } from "ol";
import { Extent, getCenter } from "ol/extent";
import { defaults as defaultInteractions, DragPan, DragRotateAndZoom, Interaction } from "ol/interaction.js";
import ImageLayer from "ol/layer/Image";
import Layer from "ol/layer/Layer";
import VectorLayer from "ol/layer/Vector";
import Map from "ol/Map";
import Projection from "ol/proj/Projection";
import Static from "ol/source/ImageStatic.js";
import VectorSource from "ol/source/Vector";
import * as React from "react";
import "./styles.css";
import Utils from "./utils";
interface IImageMapProps {
imageUri: string;
imageWidth: number;
imageHeight: number;
imageAngle?: number;
featureStyler?: any;
enableFeatureSelection?: boolean;
handleFeatureSelect?: (feature: any, isTaggle: boolean) => void;
onMapReady: () => void;
}
export class ImageMap extends React.Component<IImageMapProps> {
private map: Map;
private imageLayer: ImageLayer;
private vectorLayer: VectorLayer;
private mapElement: HTMLDivElement | null = null;
private imageExtent: number[];
private countPointerDown: number = 0;
private isSwiping: boolean = false;
private readonly VECTOR_LAYER_NAME = "vectorLayer";
private ignorePointerMoveEventCount: number = 5;
private pointerMoveEventCount: number = 0;
private vectorLayerFilter = {
layerFilter: (layer: Layer) => layer.get("name") === this.VECTOR_LAYER_NAME,
};
constructor(props: IImageMapProps) {
super(props);
this.imageExtent = [0, 0, this.props.imageWidth, this.props.imageHeight];
}
public componentDidMount() {
this.initMap();
}
public componentDidUpdate(prevProps: IImageMapProps) {
if (prevProps.imageUri !== this.props.imageUri) {
this.imageExtent = [0, 0, this.props.imageWidth, this.props.imageHeight];
this.setImage(this.props.imageUri, this.imageExtent);
}
}
public render() {
return (
<div className="map-wrapper">
<div id="map" className="map" ref={(el) => this.mapElement = el}></div>
</div>
);
}
/**
* Add one feature to the map
*/
public addFeature = (feature: Feature) => {
this.vectorLayer.getSource().addFeature(feature);
}
/**
* Add features to the map
*/
public addFeatures = (features: Feature[]) => {
this.vectorLayer.getSource().addFeatures(features);
}
/**
* Add interaction to the map
*/
public addInteraction = (interaction: Interaction) => {
this.map.addInteraction(interaction);
}
/**
* Get all features from the map
*/
public getAllFeatures = () => {
return this.vectorLayer.getSource().getFeatures();
}
/**
* Remove specific feature object from the map
*/
public removeFeature = (feature: Feature) => {
this.vectorLayer.getSource().removeFeature(feature);
}
/**
* Remove all features from the map
*/
public removeAllFeatures = () => {
this.vectorLayer.getSource().clear();
}
/**
* Remove interaction from the map
*/
public removeInteraction = (interaction: Interaction) => {
this.map.removeInteraction(interaction);
}
/**
* Get the image extent (left, top, right, bottom)
*/
public getImageExtent = () => {
return this.imageExtent;
}
/**
* Get features at specific extend
*/
public getFeaturesInExtent = (extent: Extent): Feature[] => {
const features: Feature[] = [];
this.vectorLayer.getSource().forEachFeatureInExtent(extent, (feature) => {
features.push(feature);
});
return features;
}
private initMap = () => {
const projection = this.createProjection(this.imageExtent);
this.imageLayer = new ImageLayer({
source: this.createImageSource(this.props.imageUri, projection, this.imageExtent),
});
const options: any = {};
options.name = this.VECTOR_LAYER_NAME;
options.style = this.props.featureStyler;
options.source = new VectorSource();
this.vectorLayer = new VectorLayer(options);
this.map = new Map({
interactions: defaultInteractions({ doubleClickZoom: false }).extend([new DragRotateAndZoom()]),
target: "map",
layers: [this.imageLayer, this.vectorLayer],
view: this.createMapView(projection, this.imageExtent),
});
this.map.on("pointerdown", this.handlePointerDown);
this.map.on("pointermove", this.handlePointerMove);
this.map.on("pointerup", this.handlePointerUp);
}
private setImage = (imageUri: string, imageExtent: number[]) => {
const projection = this.createProjection(imageExtent);
this.imageLayer.setSource(this.createImageSource(imageUri, projection, imageExtent));
const mapView = this.createMapView(projection, imageExtent);
this.map.setView(mapView);
}
private createProjection = (imageExtend: number[]) => {
return new Projection({
code: "xkcd-image",
units: "pixels",
extent: imageExtend,
});
}
private createMapView = (projection: Projection, imageExtend: number[]) => {
const minZoom = this.getMinimumZoom();
const rotation = (this.props.imageAngle)
? Utils.degreeToRadians((this.props.imageAngle + 360) % 360)
: 0;
return new View({
projection,
center: getCenter(imageExtend),
rotation,
zoom: minZoom,
minZoom,
});
}
private createImageSource = (imageUri: string, projection: Projection, imageExtend: number[]) => {
return new Static({
url: imageUri,
projection,
imageExtent: imageExtend,
});
}
private getMinimumZoom = () => {
// In openlayers, the image will be projected into 256x256 pixels,
// and image will be 2x larger at each zoom level.
// https://openlayers.org/en/latest/examples/min-zoom.html
const containerAspectRatio = (this.mapElement)
? (this.mapElement.clientHeight / this.mapElement.clientWidth) : 1;
const imageAspectRatio = this.props.imageHeight / this.props.imageWidth;
if (imageAspectRatio > containerAspectRatio) {
// Fit to width
return Math.LOG2E * Math.log(this.mapElement!.clientHeight / 256);
} else {
// Fit to height
return Math.LOG2E * Math.log(this.mapElement!.clientWidth / 256);
}
}
private handlePointerDown = (event: MapBrowserEvent) => {
if (!this.props.enableFeatureSelection) {
return;
}
this.countPointerDown += 1;
if (this.countPointerDown >= 2) {
this.setDragPanInteraction(true /*dragPanEnabled*/);
this.isSwiping = false;
return;
}
const isPointerOnFeature = this.map.hasFeatureAtPixel(
this.map.getEventPixel(event.originalEvent),
this.vectorLayerFilter);
if (isPointerOnFeature && this.props.handleFeatureSelect) {
const eventPixel = this.map.getEventPixel(event.originalEvent);
this.map.forEachFeatureAtPixel(
eventPixel,
(feature) => {
if (this.props.handleFeatureSelect) {
this.props.handleFeatureSelect(feature, true /*isTaggle*/);
}
},
this.vectorLayerFilter);
}
this.setDragPanInteraction(!isPointerOnFeature /*dragPanEnabled*/);
this.isSwiping = isPointerOnFeature;
}
private handlePointerMove = (event: MapBrowserEvent) => {
if (this.shouldIgnorePointerMove()) {
return;
}
// disable vertical scrolling for iOS Safari
event.preventDefault();
const eventPixel = this.map.getEventPixel(event.originalEvent);
this.map.forEachFeatureAtPixel(
eventPixel,
(feature) => {
if (this.props.handleFeatureSelect) {
this.props.handleFeatureSelect(feature, false /*isTaggle*/);
}
},
this.vectorLayerFilter);
}
private handlePointerUp = () => {
if (!this.props.enableFeatureSelection) {
return;
}
this.countPointerDown -= 1;
if (this.countPointerDown === 0) {
this.setDragPanInteraction(true /*dragPanEnabled*/);
this.isSwiping = false;
this.pointerMoveEventCount = 0;
}
}
private setDragPanInteraction = (dragPanEnabled: boolean) => {
this.map.getInteractions().forEach((interaction) => {
if (interaction instanceof DragPan) {
interaction.setActive(dragPanEnabled);
}
});
}
private shouldIgnorePointerMove = () => {
if (!this.props.enableFeatureSelection) {
return true;
}
if (!this.isSwiping) {
return true;
}
if (this.ignorePointerMoveEventCount > this.pointerMoveEventCount) {
++this.pointerMoveEventCount;
return true;
}
return false;
}
}

Просмотреть файл

@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
export default class Utils {
// convert degree to radians
public static degreeToRadians(degree: number) {
return degree * Math.PI * 2 / 360;
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
export default class Utils {
// convert degree to radians
public static degreeToRadians(degree: number) {
return degree * Math.PI * 2 / 360;
}
}

Просмотреть файл

@ -1,92 +1,92 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Action } from "redux";
import { ActionTypes } from "./actionTypes";
import {
ISaveAppSettingsAction,
IEnsureSecurityTokenAction,
} from "./applicationActions";
import {
ILoadConnectionAction,
ISaveConnectionAction,
IDeleteConnectionAction,
} from "./connectionActions";
import {
ILoadProjectAction,
ICloseProjectAction,
ISaveProjectAction,
ILoadProjectAssetsAction,
ISaveAssetMetadataAction,
ILoadAssetMetadataAction,
IDeleteProjectAction,
} from "./projectActions";
import {
IShowAppErrorAction,
IClearErrorAction,
} from "./appErrorActions";
import { ISetTitleAction } from "./appTitleActions";
/**
* Data payload dispatched from the action and delivered to reducer
*/
export interface IPayloadAction<TType, TPayload> extends Action<TType> {
payload: TPayload;
}
/**
* Creates action and validates type of action type name
* @param type Name for action being created
*/
// tslint:disable-next-line:max-line-length
export function createAction<TAction extends Action<TAction["type"]>>(type: TAction["type"]): () => Action<TAction["type"]> {
return () => ({
type,
});
}
/**
* Create action with payload
* @param type Name for action being created
*/
// tslint:disable-next-line:max-line-length
export function createPayloadAction<TAction extends IPayloadAction<TAction["type"], TAction["payload"]>>(type: TAction["type"]): (payload: TAction["payload"]) => IPayloadAction<TAction["type"], TAction["payload"]> {
return (payload: TAction["payload"]) => ({
type,
payload,
});
}
/**
* Catch-all for unregistered actions
*/
export interface IOtherAction extends Action<string> {
type: ActionTypes.ANY_OTHER_ACTION;
}
/**
* Helper instance of catch-all
*/
export const anyOtherAction = createAction<IOtherAction>(ActionTypes.ANY_OTHER_ACTION);
/**
* Used by reducers to type-check all actions
*/
export type AnyAction = IOtherAction |
ISaveAppSettingsAction |
IEnsureSecurityTokenAction |
ISaveConnectionAction |
IDeleteConnectionAction |
ILoadConnectionAction |
ISaveConnectionAction |
IDeleteConnectionAction |
ILoadProjectAction |
ICloseProjectAction |
ISaveProjectAction |
IDeleteProjectAction |
ILoadProjectAssetsAction |
ISaveAssetMetadataAction |
ILoadAssetMetadataAction |
IShowAppErrorAction |
IClearErrorAction |
ISetTitleAction;
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Action } from "redux";
import { ActionTypes } from "./actionTypes";
import {
ISaveAppSettingsAction,
IEnsureSecurityTokenAction,
} from "./applicationActions";
import {
ILoadConnectionAction,
ISaveConnectionAction,
IDeleteConnectionAction,
} from "./connectionActions";
import {
ILoadProjectAction,
ICloseProjectAction,
ISaveProjectAction,
ILoadProjectAssetsAction,
ISaveAssetMetadataAction,
ILoadAssetMetadataAction,
IDeleteProjectAction,
} from "./projectActions";
import {
IShowAppErrorAction,
IClearErrorAction,
} from "./appErrorActions";
import { ISetTitleAction } from "./appTitleActions";
/**
* Data payload dispatched from the action and delivered to reducer
*/
export interface IPayloadAction<TType, TPayload> extends Action<TType> {
payload: TPayload;
}
/**
* Creates action and validates type of action type name
* @param type Name for action being created
*/
// tslint:disable-next-line:max-line-length
export function createAction<TAction extends Action<TAction["type"]>>(type: TAction["type"]): () => Action<TAction["type"]> {
return () => ({
type,
});
}
/**
* Create action with payload
* @param type Name for action being created
*/
// tslint:disable-next-line:max-line-length
export function createPayloadAction<TAction extends IPayloadAction<TAction["type"], TAction["payload"]>>(type: TAction["type"]): (payload: TAction["payload"]) => IPayloadAction<TAction["type"], TAction["payload"]> {
return (payload: TAction["payload"]) => ({
type,
payload,
});
}
/**
* Catch-all for unregistered actions
*/
export interface IOtherAction extends Action<string> {
type: ActionTypes.ANY_OTHER_ACTION;
}
/**
* Helper instance of catch-all
*/
export const anyOtherAction = createAction<IOtherAction>(ActionTypes.ANY_OTHER_ACTION);
/**
* Used by reducers to type-check all actions
*/
export type AnyAction = IOtherAction |
ISaveAppSettingsAction |
IEnsureSecurityTokenAction |
ISaveConnectionAction |
IDeleteConnectionAction |
ILoadConnectionAction |
ISaveConnectionAction |
IDeleteConnectionAction |
ILoadProjectAction |
ICloseProjectAction |
ISaveProjectAction |
IDeleteProjectAction |
ILoadProjectAssetsAction |
ISaveAssetMetadataAction |
ILoadAssetMetadataAction |
IShowAppErrorAction |
IClearErrorAction |
ISetTitleAction;

Просмотреть файл

@ -1,36 +1,36 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* Redux Action types
*/
export enum ActionTypes {
// App
SAVE_APP_SETTINGS_SUCCESS = "SAVE_APP_SETTINGS_SUCCESS",
ENSURE_SECURITY_TOKEN_SUCCESS = "ENSURE_SECURITY_TOKEN_SUCCESS",
// Projects
LOAD_PROJECT_SUCCESS = "LOAD_PROJECT_SUCCESS",
SAVE_PROJECT_SUCCESS = "SAVE_PROJECT_SUCCESS",
DELETE_PROJECT_SUCCESS = "DELETE_PROJECT_SUCCESS",
CLOSE_PROJECT_SUCCESS = "CLOSE_PROJECT_SUCCESS",
LOAD_PROJECT_ASSETS_SUCCESS = "LOAD_PROJECT_ASSETS_SUCCESS",
UPDATE_PROJECT_TAG_SUCCESS = "UPDATE_PROJECT_TAG_SUCCESS",
DELETE_PROJECT_TAG_SUCCESS = "DELETE_PROJECT_TAG_SUCCESS",
// Connections
LOAD_CONNECTION_SUCCESS = "LOAD_CONNECTION_SUCCESS",
SAVE_CONNECTION_SUCCESS = "SAVE_CONNECTION_SUCCESS",
DELETE_CONNECTION_SUCCESS = "DELETE_CONNECTION_SUCCESS",
// Assets
SAVE_ASSET_METADATA_SUCCESS = "SAVE_ASSET_METADATA_SUCCESS",
LOAD_ASSET_METADATA_SUCCESS = "LOAD_ASSET_METADATA_SUCCESS",
ANY_OTHER_ACTION = "ANY_OTHER_ACTION_SUCCESS",
SHOW_ERROR = "SHOW_ERROR",
CLEAR_ERROR = "CLEAR_ERROR",
SET_TITLE = "SET_TITLE",
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* Redux Action types
*/
export enum ActionTypes {
// App
SAVE_APP_SETTINGS_SUCCESS = "SAVE_APP_SETTINGS_SUCCESS",
ENSURE_SECURITY_TOKEN_SUCCESS = "ENSURE_SECURITY_TOKEN_SUCCESS",
// Projects
LOAD_PROJECT_SUCCESS = "LOAD_PROJECT_SUCCESS",
SAVE_PROJECT_SUCCESS = "SAVE_PROJECT_SUCCESS",
DELETE_PROJECT_SUCCESS = "DELETE_PROJECT_SUCCESS",
CLOSE_PROJECT_SUCCESS = "CLOSE_PROJECT_SUCCESS",
LOAD_PROJECT_ASSETS_SUCCESS = "LOAD_PROJECT_ASSETS_SUCCESS",
UPDATE_PROJECT_TAG_SUCCESS = "UPDATE_PROJECT_TAG_SUCCESS",
DELETE_PROJECT_TAG_SUCCESS = "DELETE_PROJECT_TAG_SUCCESS",
// Connections
LOAD_CONNECTION_SUCCESS = "LOAD_CONNECTION_SUCCESS",
SAVE_CONNECTION_SUCCESS = "SAVE_CONNECTION_SUCCESS",
DELETE_CONNECTION_SUCCESS = "DELETE_CONNECTION_SUCCESS",
// Assets
SAVE_ASSET_METADATA_SUCCESS = "SAVE_ASSET_METADATA_SUCCESS",
LOAD_ASSET_METADATA_SUCCESS = "LOAD_ASSET_METADATA_SUCCESS",
ANY_OTHER_ACTION = "ANY_OTHER_ACTION_SUCCESS",
SHOW_ERROR = "SHOW_ERROR",
CLEAR_ERROR = "CLEAR_ERROR",
SET_TITLE = "SET_TITLE",
}

Просмотреть файл

@ -1,64 +1,64 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Dispatch, Action } from "redux";
import { IAppError } from "../../models/applicationState";
import { createPayloadAction, IPayloadAction, createAction } from "./actionCreators";
import { ActionTypes } from "./actionTypes";
/**
* Action to display alert when there's an error in the app
* @member showError
* @member clearError
* @interface
*/
export default interface IAppErrorActions {
showError(appError: IAppError): void;
clearError(): void;
}
/**
* show alert popup to indicate error
* @param appError {IAppError} the error to display in alert
* @returns {(dispatch: Dispatch) => void}
*/
export function showError(appError: IAppError): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
dispatch(showErrorAction(appError));
};
}
/**
* clear alert popup
* @returns {(dispatch: Dispatch) => void}
*/
export function clearError(): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
dispatch(clearErrorAction());
};
}
/**
* Show error action type
*/
export interface IShowAppErrorAction extends IPayloadAction<string, IAppError> {
type: ActionTypes.SHOW_ERROR;
}
/**
* Clear error action type
*/
export interface IClearErrorAction extends Action<string> {
type: ActionTypes.CLEAR_ERROR;
}
/**
* Instance of show error action
*/
export const showErrorAction = createPayloadAction<IShowAppErrorAction>(ActionTypes.SHOW_ERROR);
/**
* Instance of clear error action
* @type {() => Action<IClearErrorAction["type"]>}
*/
export const clearErrorAction = createAction<IClearErrorAction>(ActionTypes.CLEAR_ERROR);
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Dispatch, Action } from "redux";
import { IAppError } from "../../models/applicationState";
import { createPayloadAction, IPayloadAction, createAction } from "./actionCreators";
import { ActionTypes } from "./actionTypes";
/**
* Action to display alert when there's an error in the app
* @member showError
* @member clearError
* @interface
*/
export default interface IAppErrorActions {
showError(appError: IAppError): void;
clearError(): void;
}
/**
* show alert popup to indicate error
* @param appError {IAppError} the error to display in alert
* @returns {(dispatch: Dispatch) => void}
*/
export function showError(appError: IAppError): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
dispatch(showErrorAction(appError));
};
}
/**
* clear alert popup
* @returns {(dispatch: Dispatch) => void}
*/
export function clearError(): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
dispatch(clearErrorAction());
};
}
/**
* Show error action type
*/
export interface IShowAppErrorAction extends IPayloadAction<string, IAppError> {
type: ActionTypes.SHOW_ERROR;
}
/**
* Clear error action type
*/
export interface IClearErrorAction extends Action<string> {
type: ActionTypes.CLEAR_ERROR;
}
/**
* Instance of show error action
*/
export const showErrorAction = createPayloadAction<IShowAppErrorAction>(ActionTypes.SHOW_ERROR);
/**
* Instance of clear error action
* @type {() => Action<IClearErrorAction["type"]>}
*/
export const clearErrorAction = createAction<IClearErrorAction>(ActionTypes.CLEAR_ERROR);

Просмотреть файл

@ -1,38 +1,38 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Dispatch } from "redux";
import { createPayloadAction, IPayloadAction } from "./actionCreators";
import { ActionTypes } from "./actionTypes";
/**
* Action to set app title
* @member setTitle
* @interface
*/
export default interface IAppTitleActions {
setTitle(title: string): void;
}
/**
* set app title
* @param title {string} the title of app
* @returns {(dispatch: Dispatch) => void}
*/
export function setTitle(title: string): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
dispatch(setTitleAction(title));
};
}
/**
* Set app title
*/
export interface ISetTitleAction extends IPayloadAction<string, string> {
type: ActionTypes.SET_TITLE;
}
/**
* Instance of set title action
*/
export const setTitleAction = createPayloadAction<ISetTitleAction>(ActionTypes.SET_TITLE);
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Dispatch } from "redux";
import { createPayloadAction, IPayloadAction } from "./actionCreators";
import { ActionTypes } from "./actionTypes";
/**
* Action to set app title
* @member setTitle
* @interface
*/
export default interface IAppTitleActions {
setTitle(title: string): void;
}
/**
* set app title
* @param title {string} the title of app
* @returns {(dispatch: Dispatch) => void}
*/
export function setTitle(title: string): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
dispatch(setTitleAction(title));
};
}
/**
* Set app title
*/
export interface ISetTitleAction extends IPayloadAction<string, string> {
type: ActionTypes.SET_TITLE;
}
/**
* Instance of set title action
*/
export const setTitleAction = createPayloadAction<ISetTitleAction>(ActionTypes.SET_TITLE);

Просмотреть файл

@ -1,29 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { reducer } from "./appTitleReducer";
import { setTitleAction } from "../actions/appTitleActions";
import { anyOtherAction } from "../actions/actionCreators";
describe("AppTitle Reducer", () => {
let state: string;
beforeEach(() => {
state = "Welcome";
});
it("SetTitle discard previous state and return a title", () => {
const title = "Hello";
const action = setTitleAction(title);
const result = reducer(state, action);
expect(result).not.toEqual(state);
expect(result).toEqual(title);
});
it("Unknown action performs noop", () => {
const action = anyOtherAction();
const result = reducer(state, action);
expect(result).toBe(state);
});
});
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { reducer } from "./appTitleReducer";
import { setTitleAction } from "../actions/appTitleActions";
import { anyOtherAction } from "../actions/actionCreators";
describe("AppTitle Reducer", () => {
let state: string;
beforeEach(() => {
state = "Welcome";
});
it("SetTitle discard previous state and return a title", () => {
const title = "Hello";
const action = setTitleAction(title);
const result = reducer(state, action);
expect(result).not.toEqual(state);
expect(result).toEqual(title);
});
it("Unknown action performs noop", () => {
const action = anyOtherAction();
const result = reducer(state, action);
expect(result).toBe(state);
});
});

Просмотреть файл

@ -1,22 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { ActionTypes } from "../actions/actionTypes";
import { AnyAction } from "../actions/actionCreators";
/**
* App Title Reducer
* Actions handled:
* SET_TITLE
* @param {string} state
* @param {AnyAction} action
* @returns {any}
*/
export const reducer = (state: string = null, action: AnyAction) => {
switch (action.type) {
case ActionTypes.SET_TITLE:
return action.payload;
default:
return state;
}
};
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { ActionTypes } from "../actions/actionTypes";
import { AnyAction } from "../actions/actionCreators";
/**
* App Title Reducer
* Actions handled:
* SET_TITLE
* @param {string} state
* @param {AnyAction} action
* @returns {any}
*/
export const reducer = (state: string = null, action: AnyAction) => {
switch (action.type) {
case ActionTypes.SET_TITLE:
return action.payload;
default:
return state;
}
};

Просмотреть файл

@ -12,7 +12,8 @@
"ordered-imports": false,
"no-string-literal": false,
"no-bitwise": false,
"function-constructor": false
"function-constructor": false,
"linebreak-style": [true, "LF"]
},
"rulesDirectory": []
}