<commit_before>/* eslint-disable no-use-before-define */

import * as AxiosUtils from '../utils/axios';
import * as DataApi from './DataApi';
import { DATA_API } from '../constants/ApiNames';
import { MOCK_DATA_EDGE_DM, MOCK_DATA_GRAPH_DM } from '../utils/testing/MockDataModels';
import { UpdateTypes } from '../constants/types';

import {
  ASSOCIATION_PATH,
  COUNT_PATH,
  SET_ID,
  SET_PATH,
  TYPE_PATH
} from '../constants/UrlConstants';

import {
  INVALID_PARAMS,
  INVALID_PARAMS_SS,
  INVALID_PARAMS_SS_EMPTY_ARRAY_ALLOWED
} from '../utils/testing/Invalid';

import {
  genMockBaseUrl,
  genRandomString,
  genRandomUUID,
  getMockAxiosInstance
} from '../utils/testing/MockUtils';

import {
  assertApiShouldSendCorrectHttpRequest,
  testApiShouldNotThrowOnInvalidParameters,
  testApiShouldRejectOnInvalidParameters,
  testApiShouldReturnPromise,
  testApiShouldReturnNullOnInvalidParameters,
  testApiShouldSendCorrectHttpRequest,
  testApiShouldUseCorrectAxiosInstance
} from '../utils/testing/TestUtils';

/*
 * mocks
 */

const MOCK_BASE_URL = genMockBaseUrl();
const MOCK_FILE_TYPE = 'json';

jest.mock('../utils/axios');
AxiosUtils.getApiBaseUrl.mockImplementation(() => MOCK_BASE_URL);
AxiosUtils.getApiAxiosInstance.mockImplementation(() => getMockAxiosInstance());

/*
 * tests
 */

describe('DataApi', () => {

  afterEach(() => {
    jest.clearAllMocks();
  });

  clearEntitySet();
  clearEntityFromEntitySet();
  createAssociations();
  createEntityAndAssociationData();
  createOrMergeEntityData();
  getEntityData();
  getEntitySetData();
  getEntitySetDataFileUrl();
  getEntitySetSize();
  replaceEntityData();
  replaceEntityInEntitySet();
  replaceEntityInEntitySetUsingFqns();
});

function clearEntityFromEntitySet() {

  describe('clearEntityFromEntitySet()', () => {

    const apiToTest = DataApi.clearEntityFromEntitySet;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();

    const validParams = [mockEntitySetId, mockEntityKeyId];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}/${mockEntityKeyId}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'delete');
  });
}

function clearEntitySet() {

  describe('clearEntitySet()', () => {

    const apiToTest = DataApi.clearEntitySet;
    const mockEntitySetId = genRandomUUID();

    const validParams = [mockEntitySetId];
    const invalidParams = [INVALID_PARAMS_SS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'delete');
  });
}

function createAssociations() {

  describe('createAssociations()', () => {

    const apiToTest = DataApi.createAssociations;
    const validParams = [MOCK_DATA_EDGE_DM];
    const invalidParams = [INVALID_PARAMS];
    const axiosParams = [`/${ASSOCIATION_PATH}`, MOCK_DATA_EDGE_DM];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}

function createEntityAndAssociationData() {

  describe('createEntityAndAssociationData()', () => {

    const apiToTest = DataApi.createEntityAndAssociationData;
    const validParams = [MOCK_DATA_GRAPH_DM];
    const invalidParams = [INVALID_PARAMS];
    const axiosParams = ['/', MOCK_DATA_GRAPH_DM];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}

function createOrMergeEntityData() {

  describe('createOrMergeEntityData()', () => {

    const apiToTest = DataApi.createOrMergeEntityData;
    const mockEntitySetId = genRandomUUID();
    const mockEntityData = [{
      [`${genRandomUUID()}`]: ['value_1', 'value_2'],
      [`${genRandomUUID()}`]: ['value_3', 'value_4']
    }];

    const validParams = [mockEntitySetId, mockEntityData];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS];
    const axiosParams = [`/${SET_PATH}/?${SET_ID}=${mockEntitySetId}`, mockEntityData];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}

function getEntityData() {

  describe('getEntityData()', () => {

    const apiToTest = DataApi.getEntityData;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();

    const validParams = [mockEntitySetId, mockEntityKeyId];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS];
    const axiosParams = [`/${mockEntitySetId}/${mockEntityKeyId}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'get');
  });
}

function getEntitySetData() {

  describe('getEntitySetData()', () => {

    const apiToTest = DataApi.getEntitySetData;
    const mockEntityKeyId = genRandomUUID();
    const mockEntitySetId = genRandomUUID();
    const mockPropertyTypeId = genRandomUUID();

    const validParams = [
      mockEntitySetId,
      [mockPropertyTypeId],
      [mockEntityKeyId]
    ];

    const invalidParams = [
      INVALID_PARAMS_SS,
      INVALID_PARAMS_SS_EMPTY_ARRAY_ALLOWED,
      INVALID_PARAMS_SS_EMPTY_ARRAY_ALLOWED
    ];

    describe('should send a POST request with the correct params', () => {

      test('+propertyTypeIds, +entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId,
          [mockPropertyTypeId],
          [mockEntityKeyId]
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          {
            ids: [mockEntityKeyId],
            properties: [mockPropertyTypeId]
          }
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

      test('-propertyTypeIds, +entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId,
          undefined,
          [mockEntityKeyId]
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          { ids: [mockEntityKeyId] }
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

      test('+propertyTypeIds, -entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId,
          [mockPropertyTypeId],
          undefined
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          { properties: [mockPropertyTypeId] }
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

      test('-propertyTypeIds, -entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          {}
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

    });

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
  });
}

function getEntitySetDataFileUrl() {

  describe('getEntitySetDataFileUrl()', () => {

    const apiToTest = DataApi.getEntitySetDataFileUrl;
    const mockEntitySetId = genRandomUUID();

    const validParams = [
      mockEntitySetId,
      MOCK_FILE_TYPE
    ];

    const invalidParams = [
      INVALID_PARAMS_SS,
      INVALID_PARAMS
    ];

    test('should return the correct URL', () => {

      expect(DataApi.getEntitySetDataFileUrl(mockEntitySetId, MOCK_FILE_TYPE)).toEqual(
        `${MOCK_BASE_URL}/${SET_PATH}/${mockEntitySetId}?fileType=${MOCK_FILE_TYPE}`
      );
    });

    test('should correctly set the "fileType" query param as lowercase', () => {

      expect(DataApi.getEntitySetDataFileUrl(mockEntitySetId, MOCK_FILE_TYPE.toUpperCase())).toEqual(
        `${MOCK_BASE_URL}/${SET_PATH}/${mockEntitySetId}?fileType=${MOCK_FILE_TYPE}`
      );
    });

    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldReturnNullOnInvalidParameters(apiToTest, validParams, invalidParams);

  });
}

function getEntitySetSize() {

  describe('getEntitySetSize()', () => {

    const apiToTest = DataApi.getEntitySetSize;
    const mockEntitySetId = genRandomUUID();

    const validParams = [mockEntitySetId];
    const invalidParams = [INVALID_PARAMS_SS];
    const axiosParams = [`/${mockEntitySetId}/${COUNT_PATH}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'get');
  });
}

function replaceEntityData() {

  describe('replaceEntityData()', () => {

    const apiToTest = DataApi.replaceEntityData;
    const mockEntitySetId = genRandomUUID();
    const mockEntityData = {
      [`${genRandomUUID()}`]: {
        [`${genRandomUUID()}`]: ['value_1', 'value_2'],
        [`${genRandomUUID()}`]: ['value_3', 'value_4']
      }
    };

    // TODO: generate invalid params for the "entities" param

    const validParams = [mockEntitySetId, mockEntityData, false];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS, []];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);

    // TODO: add tests to validate "partial" query param is being set correctly for invalid values
    describe('should send a PUT request with the correct params', () => {

      test('type=PartialReplace', () => {
        const apiInvocationParams = [mockEntitySetId, mockEntityData, true];
        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}?${TYPE_PATH}=${UpdateTypes.PartialReplace}`,
          mockEntityData
        ];
        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'put');
      });

      test('type=Replace', () => {
        const apiInvocationParams = [mockEntitySetId, mockEntityData, false];
        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}?${TYPE_PATH}=${UpdateTypes.Replace}`,
          mockEntityData
        ];
        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'put');
      });
    });
  });
}

function replaceEntityInEntitySet() {

  describe('replaceEntityInEntitySet()', () => {

    const apiToTest = DataApi.replaceEntityInEntitySet;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();
    const mockEntity = {
      [`${genRandomUUID()}`]: ['value_1', 'value_2']
    };

    // TODO: generate invalid params for the "entity" param

    const validParams = [mockEntitySetId, mockEntityKeyId, mockEntity];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS, INVALID_PARAMS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}/${mockEntityKeyId}`, mockEntity];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'put');
  });
}

function replaceEntityInEntitySetUsingFqns() {

  describe('replaceEntityInEntitySetUsingFqns()', () => {

    const apiToTest = DataApi.replaceEntityInEntitySetUsingFqns;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();
    const mockEntity = {
      [`${genRandomString()}.${genRandomString()}`]: ['value_1', 'value_2']
    };

    // TODO: generate invalid params for the "entity" param

    const validParams = [mockEntitySetId, mockEntityKeyId, mockEntity];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS, INVALID_PARAMS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}/${mockEntityKeyId}`, mockEntity];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}
<commit_msg>Add tests for deleteAllEntitiesFromEntitySet<commit_after>/* eslint-disable no-use-before-define */

import * as AxiosUtils from '../utils/axios';
import * as DataApi from './DataApi';
import { DATA_API } from '../constants/ApiNames';
import { MOCK_DATA_EDGE_DM, MOCK_DATA_GRAPH_DM } from '../utils/testing/MockDataModels';
import { UpdateTypes, DeleteTypes } from '../constants/types';

import {
  ASSOCIATION_PATH,
  COUNT_PATH,
  SET_ID,
  SET_PATH,
  TYPE_PATH
} from '../constants/UrlConstants';

import {
  INVALID_PARAMS,
  INVALID_PARAMS_SS,
  INVALID_PARAMS_SS_EMPTY_ARRAY_ALLOWED
} from '../utils/testing/Invalid';

import {
  genMockBaseUrl,
  genRandomString,
  genRandomUUID,
  getMockAxiosInstance
} from '../utils/testing/MockUtils';

import {
  assertApiShouldSendCorrectHttpRequest,
  testApiShouldNotThrowOnInvalidParameters,
  testApiShouldRejectOnInvalidParameters,
  testApiShouldReturnPromise,
  testApiShouldReturnNullOnInvalidParameters,
  testApiShouldSendCorrectHttpRequest,
  testApiShouldUseCorrectAxiosInstance
} from '../utils/testing/TestUtils';

/*
 * mocks
 */

const MOCK_BASE_URL = genMockBaseUrl();
const MOCK_FILE_TYPE = 'json';

jest.mock('../utils/axios');
AxiosUtils.getApiBaseUrl.mockImplementation(() => MOCK_BASE_URL);
AxiosUtils.getApiAxiosInstance.mockImplementation(() => getMockAxiosInstance());

/*
 * tests
 */

describe('DataApi', () => {

  afterEach(() => {
    jest.clearAllMocks();
  });

  clearEntitySet();
  clearEntityFromEntitySet();
  createAssociations();
  createEntityAndAssociationData();
  createOrMergeEntityData();
  deleteAllEntitiesFromEntitySet();
  getEntityData();
  getEntitySetData();
  getEntitySetDataFileUrl();
  getEntitySetSize();
  replaceEntityData();
  replaceEntityInEntitySet();
  replaceEntityInEntitySetUsingFqns();
});

function clearEntityFromEntitySet() {

  describe('clearEntityFromEntitySet()', () => {

    const apiToTest = DataApi.clearEntityFromEntitySet;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();

    const validParams = [mockEntitySetId, mockEntityKeyId];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}/${mockEntityKeyId}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'delete');
  });
}

function clearEntitySet() {

  describe('clearEntitySet()', () => {

    const apiToTest = DataApi.clearEntitySet;
    const mockEntitySetId = genRandomUUID();

    const validParams = [mockEntitySetId];
    const invalidParams = [INVALID_PARAMS_SS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'delete');
  });
}

function createAssociations() {

  describe('createAssociations()', () => {

    const apiToTest = DataApi.createAssociations;
    const validParams = [MOCK_DATA_EDGE_DM];
    const invalidParams = [INVALID_PARAMS];
    const axiosParams = [`/${ASSOCIATION_PATH}`, MOCK_DATA_EDGE_DM];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}

function createEntityAndAssociationData() {

  describe('createEntityAndAssociationData()', () => {

    const apiToTest = DataApi.createEntityAndAssociationData;
    const validParams = [MOCK_DATA_GRAPH_DM];
    const invalidParams = [INVALID_PARAMS];
    const axiosParams = ['/', MOCK_DATA_GRAPH_DM];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}

function createOrMergeEntityData() {

  describe('createOrMergeEntityData()', () => {

    const apiToTest = DataApi.createOrMergeEntityData;
    const mockEntitySetId = genRandomUUID();
    const mockEntityData = [{
      [`${genRandomUUID()}`]: ['value_1', 'value_2'],
      [`${genRandomUUID()}`]: ['value_3', 'value_4']
    }];

    const validParams = [mockEntitySetId, mockEntityData];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS];
    const axiosParams = [`/${SET_PATH}/?${SET_ID}=${mockEntitySetId}`, mockEntityData];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}

function deleteAllEntitiesFromEntitySet() {

  describe('deleteAllEntitiesFromEntitySet()', () => {

    const apiToTest = DataApi.deleteAllEntitiesFromEntitySet;
    const mockEntitySetId = genRandomUUID();

    const validParams = [mockEntitySetId, 'Soft'];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);

    test('type=Soft', () => {
      const apiInvocationParams = [mockEntitySetId, 'Soft'];
      const expectedAxiosParams = [`/${SET_PATH}/${mockEntitySetId}/all?${TYPE_PATH}=${DeleteTypes.Soft}`];
      return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'delete');
    });

    test('type=Hard', () => {
      const apiInvocationParams = [mockEntitySetId, 'Hard'];
      const expectedAxiosParams = [`/${SET_PATH}/${mockEntitySetId}/all?${TYPE_PATH}=${DeleteTypes.Hard}`];
      return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'delete');
    });
  });
}

function getEntityData() {

  describe('getEntityData()', () => {

    const apiToTest = DataApi.getEntityData;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();

    const validParams = [mockEntitySetId, mockEntityKeyId];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS];
    const axiosParams = [`/${mockEntitySetId}/${mockEntityKeyId}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'get');
  });
}

function getEntitySetData() {

  describe('getEntitySetData()', () => {

    const apiToTest = DataApi.getEntitySetData;
    const mockEntityKeyId = genRandomUUID();
    const mockEntitySetId = genRandomUUID();
    const mockPropertyTypeId = genRandomUUID();

    const validParams = [
      mockEntitySetId,
      [mockPropertyTypeId],
      [mockEntityKeyId]
    ];

    const invalidParams = [
      INVALID_PARAMS_SS,
      INVALID_PARAMS_SS_EMPTY_ARRAY_ALLOWED,
      INVALID_PARAMS_SS_EMPTY_ARRAY_ALLOWED
    ];

    describe('should send a POST request with the correct params', () => {

      test('+propertyTypeIds, +entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId,
          [mockPropertyTypeId],
          [mockEntityKeyId]
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          {
            ids: [mockEntityKeyId],
            properties: [mockPropertyTypeId]
          }
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

      test('-propertyTypeIds, +entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId,
          undefined,
          [mockEntityKeyId]
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          { ids: [mockEntityKeyId] }
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

      test('+propertyTypeIds, -entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId,
          [mockPropertyTypeId],
          undefined
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          { properties: [mockPropertyTypeId] }
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

      test('-propertyTypeIds, -entityKeyIds', () => {

        const apiInvocationParams = [
          mockEntitySetId
        ];

        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}`,
          {}
        ];

        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'post');
      });

    });

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
  });
}

function getEntitySetDataFileUrl() {

  describe('getEntitySetDataFileUrl()', () => {

    const apiToTest = DataApi.getEntitySetDataFileUrl;
    const mockEntitySetId = genRandomUUID();

    const validParams = [
      mockEntitySetId,
      MOCK_FILE_TYPE
    ];

    const invalidParams = [
      INVALID_PARAMS_SS,
      INVALID_PARAMS
    ];

    test('should return the correct URL', () => {

      expect(DataApi.getEntitySetDataFileUrl(mockEntitySetId, MOCK_FILE_TYPE)).toEqual(
        `${MOCK_BASE_URL}/${SET_PATH}/${mockEntitySetId}?fileType=${MOCK_FILE_TYPE}`
      );
    });

    test('should correctly set the "fileType" query param as lowercase', () => {

      expect(DataApi.getEntitySetDataFileUrl(mockEntitySetId, MOCK_FILE_TYPE.toUpperCase())).toEqual(
        `${MOCK_BASE_URL}/${SET_PATH}/${mockEntitySetId}?fileType=${MOCK_FILE_TYPE}`
      );
    });

    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldReturnNullOnInvalidParameters(apiToTest, validParams, invalidParams);

  });
}

function getEntitySetSize() {

  describe('getEntitySetSize()', () => {

    const apiToTest = DataApi.getEntitySetSize;
    const mockEntitySetId = genRandomUUID();

    const validParams = [mockEntitySetId];
    const invalidParams = [INVALID_PARAMS_SS];
    const axiosParams = [`/${mockEntitySetId}/${COUNT_PATH}`];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'get');
  });
}

function replaceEntityData() {

  describe('replaceEntityData()', () => {

    const apiToTest = DataApi.replaceEntityData;
    const mockEntitySetId = genRandomUUID();
    const mockEntityData = {
      [`${genRandomUUID()}`]: {
        [`${genRandomUUID()}`]: ['value_1', 'value_2'],
        [`${genRandomUUID()}`]: ['value_3', 'value_4']
      }
    };

    // TODO: generate invalid params for the "entities" param

    const validParams = [mockEntitySetId, mockEntityData, false];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS, []];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);

    // TODO: add tests to validate "partial" query param is being set correctly for invalid values
    describe('should send a PUT request with the correct params', () => {

      test('type=PartialReplace', () => {
        const apiInvocationParams = [mockEntitySetId, mockEntityData, true];
        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}?${TYPE_PATH}=${UpdateTypes.PartialReplace}`,
          mockEntityData
        ];
        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'put');
      });

      test('type=Replace', () => {
        const apiInvocationParams = [mockEntitySetId, mockEntityData, false];
        const expectedAxiosParams = [
          `/${SET_PATH}/${mockEntitySetId}?${TYPE_PATH}=${UpdateTypes.Replace}`,
          mockEntityData
        ];
        return assertApiShouldSendCorrectHttpRequest(apiToTest, apiInvocationParams, expectedAxiosParams, 'put');
      });
    });
  });
}

function replaceEntityInEntitySet() {

  describe('replaceEntityInEntitySet()', () => {

    const apiToTest = DataApi.replaceEntityInEntitySet;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();
    const mockEntity = {
      [`${genRandomUUID()}`]: ['value_1', 'value_2']
    };

    // TODO: generate invalid params for the "entity" param

    const validParams = [mockEntitySetId, mockEntityKeyId, mockEntity];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS, INVALID_PARAMS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}/${mockEntityKeyId}`, mockEntity];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'put');
  });
}

function replaceEntityInEntitySetUsingFqns() {

  describe('replaceEntityInEntitySetUsingFqns()', () => {

    const apiToTest = DataApi.replaceEntityInEntitySetUsingFqns;
    const mockEntitySetId = genRandomUUID();
    const mockEntityKeyId = genRandomUUID();
    const mockEntity = {
      [`${genRandomString()}.${genRandomString()}`]: ['value_1', 'value_2']
    };

    // TODO: generate invalid params for the "entity" param

    const validParams = [mockEntitySetId, mockEntityKeyId, mockEntity];
    const invalidParams = [INVALID_PARAMS_SS, INVALID_PARAMS_SS, INVALID_PARAMS];
    const axiosParams = [`/${SET_PATH}/${mockEntitySetId}/${mockEntityKeyId}`, mockEntity];

    testApiShouldReturnPromise(apiToTest, validParams);
    testApiShouldUseCorrectAxiosInstance(apiToTest, validParams, DATA_API);
    testApiShouldNotThrowOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldRejectOnInvalidParameters(apiToTest, validParams, invalidParams);
    testApiShouldSendCorrectHttpRequest(apiToTest, validParams, axiosParams, 'post');
  });
}
<|endoftext|>


<commit_before>import React from 'react'
import AlgoliaLogo from './AlgoliaLogo'

const PoweredBy = () =>

    Powered by <AlgoliaLogo className='grow v-mid' style={{width: '48px'}} />

const Logo = () =>

function Footer () {
  return (

        © 2016 <Logo /> v{APP_VERSION}

      <PoweredBy />

          Language

          Terms of Use

          Privacy

  )
}

export default Footer
<commit_msg>Fix lint<commit_after>/* global APP_VERSION */

import React from 'react'
import AlgoliaLogo from './AlgoliaLogo'

const PoweredBy = () =>

    Powered by <AlgoliaLogo className='grow v-mid' style={{width: '48px'}} />

const Logo = () =>

function Footer () {
  return (

        © 2016 <Logo /> v{APP_VERSION}

      <PoweredBy />

          Language

          Terms of Use

          Privacy

  )
}

export default Footer
<|endoftext|>


<commit_before>/**
 * This code is mostly from the old Etherpad. Please help us to comment this code.
 * This helps other people to understand this code better and helps them to improve it.
 * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
 */

// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/colorutils.js
// THIS FILE IS ALSO SERVED AS CLIENT-SIDE JS
/**
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const colorutils = {};

// Check that a given value is a css hex color value, e.g.
// "#ffffff" or "#fff"
colorutils.isCssHex = function (cssColor) {
  return /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(cssColor);
};

// "#ffffff" or "#fff" or "ffffff" or "fff" to [1.0, 1.0, 1.0]
colorutils.css2triple = function (cssColor) {
  const sixHex = colorutils.css2sixhex(cssColor);

  function hexToFloat(hh) {
    return Number(`0x${hh}`) / 255;
  }
  return [hexToFloat(sixHex.substr(0, 2)), hexToFloat(sixHex.substr(2, 2)), hexToFloat(sixHex.substr(4, 2))];
};

// "#ffffff" or "#fff" or "ffffff" or "fff" to "ffffff"
colorutils.css2sixhex = function (cssColor) {
  let h = /[0-9a-fA-F]+/.exec(cssColor)[0];
  if (h.length != 6) {
    const a = h.charAt(0);
    const b = h.charAt(1);
    const c = h.charAt(2);
    h = a + a + b + b + c + c;
  }
  return h;
};

// [1.0, 1.0, 1.0] -> "#ffffff"
colorutils.triple2css = function (triple) {
  function floatToHex(n) {
    const n2 = colorutils.clamp(Math.round(n * 255), 0, 255);
    return (`0${n2.toString(16)}`).slice(-2);
  }
  return `#${floatToHex(triple[0])}${floatToHex(triple[1])}${floatToHex(triple[2])}`;
};

colorutils.clamp = function (v, bot, top) {
  return v < bot ? bot : (v > top ? top : v);
};
colorutils.min3 = function (a, b, c) {
  return (a < b) ? (a < c ? a : c) : (b < c ? b : c);
};
colorutils.max3 = function (a, b, c) {
  return (a > b) ? (a > c ? a : c) : (b > c ? b : c);
};
colorutils.colorMin = function (c) {
  return colorutils.min3(c[0], c[1], c[2]);
};
colorutils.colorMax = function (c) {
  return colorutils.max3(c[0], c[1], c[2]);
};
colorutils.scale = function (v, bot, top) {
  return colorutils.clamp(bot + v * (top - bot), 0, 1);
};
colorutils.unscale = function (v, bot, top) {
  return colorutils.clamp((v - bot) / (top - bot), 0, 1);
};

colorutils.scaleColor = function (c, bot, top) {
  return [colorutils.scale(c[0], bot, top), colorutils.scale(c[1], bot, top), colorutils.scale(c[2], bot, top)];
};

colorutils.unscaleColor = function (c, bot, top) {
  return [colorutils.unscale(c[0], bot, top), colorutils.unscale(c[1], bot, top), colorutils.unscale(c[2], bot, top)];
};

colorutils.luminosity = function (c) {
  // rule of thumb for RGB brightness; 1.0 is white
  return c[0] * 0.30 + c[1] * 0.59 + c[2] * 0.11;
};

colorutils.saturate = function (c) {
  const min = colorutils.colorMin(c);
  const max = colorutils.colorMax(c);
  if (max - min <= 0) return [1.0, 1.0, 1.0];
  return colorutils.unscaleColor(c, min, max);
};

colorutils.blend = function (c1, c2, t) {
  return [colorutils.scale(t, c1[0], c2[0]), colorutils.scale(t, c1[1], c2[1]), colorutils.scale(t, c1[2], c2[2])];
};

colorutils.invert = function (c) {
  return [1 - c[0], 1 - c[1], 1 - c[2]];
};

colorutils.complementary = function (c) {
  const inv = colorutils.invert(c);
  return [
    (inv[0] >= c[0]) ? Math.min(inv[0] * 1.30, 1) : (c[0] * 0.30),
    (inv[1] >= c[1]) ? Math.min(inv[1] * 1.59, 1) : (c[1] * 0.59),
    (inv[2] >= c[2]) ? Math.min(inv[2] * 1.11, 1) : (c[2] * 0.11),
  ];
};

colorutils.textColorFromBackgroundColor = function (bgcolor, skinName) {
  const white = skinName == 'colibris' ? 'var(--super-light-color)' : '#fff';
  const black = skinName == 'colibris' ? 'var(--super-dark-color)' : '#222';

  return colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5 ? white : black;
};

exports.colorutils = colorutils;
<commit_msg>lint: colorutils.js<commit_after>'use strict';

/**
 * This code is mostly from the old Etherpad. Please help us to comment this code.
 * This helps other people to understand this code better and helps them to improve it.
 * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
 */

// DO NOT EDIT THIS FILE, edit infrastructure/ace/www/colorutils.js
// THIS FILE IS ALSO SERVED AS CLIENT-SIDE JS
/**
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const colorutils = {};

// Check that a given value is a css hex color value, e.g.
// "#ffffff" or "#fff"
colorutils.isCssHex = (cssColor) => /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(cssColor);

// "#ffffff" or "#fff" or "ffffff" or "fff" to [1.0, 1.0, 1.0]
colorutils.css2triple = (cssColor) => {
  const sixHex = colorutils.css2sixhex(cssColor);

  const hexToFloat = (hh) => Number(`0x${hh}`) / 255;
  return [
    hexToFloat(sixHex.substr(0, 2)),
    hexToFloat(sixHex.substr(2, 2)),
    hexToFloat(sixHex.substr(4, 2)),
  ];
};

// "#ffffff" or "#fff" or "ffffff" or "fff" to "ffffff"
colorutils.css2sixhex = (cssColor) => {
  let h = /[0-9a-fA-F]+/.exec(cssColor)[0];
  if (h.length !== 6) {
    const a = h.charAt(0);
    const b = h.charAt(1);
    const c = h.charAt(2);
    h = a + a + b + b + c + c;
  }
  return h;
};

// [1.0, 1.0, 1.0] -> "#ffffff"
colorutils.triple2css = (triple) => {
  const floatToHex = (n) => {
    const n2 = colorutils.clamp(Math.round(n * 255), 0, 255);
    return (`0${n2.toString(16)}`).slice(-2);
  };
  return `#${floatToHex(triple[0])}${floatToHex(triple[1])}${floatToHex(triple[2])}`;
};

colorutils.clamp = (v, bot, top) => v < bot ? bot : (v > top ? top : v);
colorutils.min3 = (a, b, c) => (a < b) ? (a < c ? a : c) : (b < c ? b : c);
colorutils.max3 = (a, b, c) => (a > b) ? (a > c ? a : c) : (b > c ? b : c);
colorutils.colorMin = (c) => colorutils.min3(c[0], c[1], c[2]);
colorutils.colorMax = (c) => colorutils.max3(c[0], c[1], c[2]);
colorutils.scale = (v, bot, top) => colorutils.clamp(bot + v * (top - bot), 0, 1);
colorutils.unscale = (v, bot, top) => colorutils.clamp((v - bot) / (top - bot), 0, 1);

colorutils.scaleColor = (c, bot, top) => [
  colorutils.scale(c[0], bot, top),
  colorutils.scale(c[1], bot, top),
  colorutils.scale(c[2], bot, top),
];

colorutils.unscaleColor = (c, bot, top) => [
  colorutils.unscale(c[0], bot, top),
  colorutils.unscale(c[1], bot, top),
  colorutils.unscale(c[2], bot, top),
];

// rule of thumb for RGB brightness; 1.0 is white
colorutils.luminosity = (c) => c[0] * 0.30 + c[1] * 0.59 + c[2] * 0.11;

colorutils.saturate = (c) => {
  const min = colorutils.colorMin(c);
  const max = colorutils.colorMax(c);
  if (max - min <= 0) return [1.0, 1.0, 1.0];
  return colorutils.unscaleColor(c, min, max);
};

colorutils.blend = (c1, c2, t) => [
  colorutils.scale(t, c1[0], c2[0]),
  colorutils.scale(t, c1[1], c2[1]),
  colorutils.scale(t, c1[2], c2[2]),
];

colorutils.invert = (c) => [1 - c[0], 1 - c[1], 1 - c[2]];

colorutils.complementary = (c) => {
  const inv = colorutils.invert(c);
  return [
    (inv[0] >= c[0]) ? Math.min(inv[0] * 1.30, 1) : (c[0] * 0.30),
    (inv[1] >= c[1]) ? Math.min(inv[1] * 1.59, 1) : (c[1] * 0.59),
    (inv[2] >= c[2]) ? Math.min(inv[2] * 1.11, 1) : (c[2] * 0.11),
  ];
};

colorutils.textColorFromBackgroundColor = (bgcolor, skinName) => {
  const white = skinName === 'colibris' ? 'var(--super-light-color)' : '#fff';
  const black = skinName === 'colibris' ? 'var(--super-dark-color)' : '#222';

  return colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5 ? white : black;
};

exports.colorutils = colorutils;
<|endoftext|>


<commit_before>/* eslint-disable global-require */
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers/rootReducer';
import thunk from 'redux-thunk';

let middleware = [thunk];

if (process.env.NODE_ENV !== 'production') {
	const reduxImmutableStateInvariant = require('redux-immutable-state-invariant')();
	const createLogger = require('redux-logger');

	const logger = createLogger({ collapsed: true });
	middleware = [...middleware, reduxImmutableStateInvariant, logger];
} else {
	middleware = [...middleware];
}

export default function configureStore(initialState) {
	return createStore(
		rootReducer,
		initialState,
		applyMiddleware(...middleware)
	);
}<commit_msg>Changed to __DEV__<commit_after>/* eslint-disable global-require */
/* eslint-disable no-undef */
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers/rootReducer';
import thunk from 'redux-thunk';

let middleware = [thunk];

if (__DEV__) {
	const reduxImmutableStateInvariant = require('redux-immutable-state-invariant')();
	const createLogger = require('redux-logger');

	const logger = createLogger({ collapsed: true });
	middleware = [...middleware, reduxImmutableStateInvariant, logger];
} else {
	middleware = [...middleware];
}

export default function configureStore(initialState) {
	return createStore(
		rootReducer,
		initialState,
		applyMiddleware(...middleware)
	);
}<|endoftext|>


<commit_before>// Manage rendering styles
import ShaderProgram from '../gl/shader_program';
import mergeObjects from '../utils/merge';
import Geo from '../utils/geo';
import WorkerBroker from '../utils/worker_broker';
import log from '../utils/log';

import {Polygons} from './polygons/polygons';
import {Lines} from './lines/lines';
import {Points} from './points/points';
import {TextStyle} from './text/text';
import {RasterStyle} from './raster/raster';

import style_globals_source from './style_globals.glsl';
import selection_globals_source from '../selection/selection_globals.glsl';
import selection_vertex_source from '../selection/selection_vertex.glsl';

export class StyleManager {

    constructor () {
        this.styles = {};
        this.base_styles = {};

        // Add built-in rendering styles
        this.register(Object.create(Polygons));
        this.register(Object.create(Lines));
        this.register(Object.create(Points));
        this.register(Object.create(TextStyle));
        this.register(Object.create(RasterStyle));
    }

    // Global configuration for all styles
    init () {
        ShaderProgram.removeBlock('global');
        ShaderProgram.removeBlock('setup');

        // Model and world position accessors, layer re-ordering function
        ShaderProgram.addBlock('global', style_globals_source);

        // Feature selection global
        ShaderProgram.addBlock('global', selection_globals_source);

        // Feature selection vertex shader support
        ShaderProgram.replaceBlock('setup', selection_vertex_source);

        // Minimum value for float comparisons
        ShaderProgram.defines.TANGRAM_EPSILON = 0.00001;

        // Minimum depth buffer value separating each `order` unit
        // Assume min 16-bit depth buffer, in practice uses 14-bits, 1 extra bit to handle virtual half-layers
        // for outlines (inserted in between layers), another extra bit to prevent precision loss
        ShaderProgram.defines.TANGRAM_LAYER_DELTA = 1 / (1 << 14);

        // Internal tile scale
        ShaderProgram.defines.TANGRAM_TILE_SCALE =
            `vec3(${Geo.tile_scale}., ${Geo.tile_scale}., u_meters_per_pixel * ${Geo.tile_size}.)`;

        // Increases precision for height values
        ShaderProgram.defines.TANGRAM_HEIGHT_SCALE = Geo.height_scale;

        // Alpha discard threshold (substitute for alpha blending)
        ShaderProgram.defines.TANGRAM_ALPHA_TEST = 0.5;

        // Reset dash texture cache
        Lines.dash_textures = {};
    }

    // Destroy all styles for a given GL context
    destroy (gl) {
        Object.keys(this.styles).forEach((_name) => {
            let style = this.styles[_name];
            if (style.gl === gl) {
                log('trace', `StyleManager.destroy: destroying render style ${style.name}`);

                if (style.base) {
                    this.remove(style.name);
                }
                style.destroy();
            }
        });
    }

    // Register a style
    register (style) {
        this.styles[style.name] = style;
        this.base_styles[style.name] = style;
    }

    // Remove a style
    remove (name) {
        delete this.styles[name];
    }

    mix (style, styles) {
        // Exit early if we have already applied mixins to this style
        if (style.mixed) {
            return style;
        }
        style.mixed = {};

        // Mixin sources, in order
        let sources = [];
        if (style.mix) {
            if (Array.isArray(style.mix)) {
                sources.push(...style.mix);
            }
            else {
                sources.push(style.mix);
            }
            sources = sources.map(x => styles[x]).filter(x => x && x !== style); // TODO: warning on trying to mix into self

            // Track which styles were mixed into this one
            sources.forEach(s => style.mixed[s.name] = true);
        }
        sources.push(style);

        // Flags - OR'd, true if any style has it set
        style.animated = sources.some(x => x && x.animated);
        style.texcoords = sources.some(x => x && x.texcoords);

        // Overwrites - last definition wins
        style.base = sources.map(x => x.base).filter(x => x).pop();
        style.lighting = sources.map(x => x.lighting).filter(x => x != null).pop();
        style.texture = sources.map(x => x.texture).filter(x => x).pop();
        style.raster = sources.map(x => x.raster).filter(x => x != null).pop();
        style.dash = sources.map(x => x.dash).filter(x => x != null).pop();
        style.dash_background_color = sources.map(x => x.dash_background_color).filter(x => x != null).pop();
        if (sources.some(x => x.hasOwnProperty('blend') && x.blend)) {
            // only mix blend if explicitly set, otherwise let base style choose blending mode
            // hasOwnProperty check gives preference to base style prototype
            style.blend = sources.map(x => x.hasOwnProperty('blend') && x.blend).filter(x => x).pop();
        }
        style.blend_order = sources.map(x => x.blend_order).filter(x => x != null).pop();

        // Merges - property-specific rules for merging values
        style.defines = Object.assign({}, ...sources.map(x => x.defines).filter(x => x)); // internal defines (not user-defined)
        style.material = Object.assign({}, ...sources.map(x => x.material).filter(x => x));

        let draws = sources.map(x => x.draw).filter(x => x); // draw defaults
        if (draws.length > 0) {
            style.draw = mergeObjects({}, ...draws);
        }

        // Mix shader properties
        this.mixShaders(style, styles, sources);
        return style;
    }

    // Mix the propertes in the "shaders" block
    mixShaders (style, styles, sources) {
        let shaders = {}; // newly mixed shaders properties
        let shader_merges = sources.map(x => x.shaders).filter(x => x); // just the source styles with shader properties

        // Defines
        shaders.defines = Object.assign({}, ...shader_merges.map(x => x.defines).filter(x => x));

        // Uniforms
        shaders.uniforms = {};  // uniforms for this style, both explicitly defined, and mixed from other styles
        shaders._uniforms = (style.shaders && style.shaders.uniforms) || {}; // uniforms explicitly defined by *this* style
        shaders._uniform_scopes = {}; // tracks which style each uniform originated from (this one, or ancestor)

        // Mix in uniforms from ancestors, providing means to access
        sources
            .filter(x => x.shaders && x.shaders.uniforms)
            .forEach(x => {
                for (let u in x.shaders.uniforms) {
                    shaders._uniform_scopes[u] = x.name;

                    // Define getter and setter for this uniform
                    // Getter returns value for this style if present, otherwise asks appropriate ancestor for it
                    // Setter sets the value for this style (whether previously present in this style or not)
                    // Mimics JS prototype/hasOwnProperty behavior, but with multiple ancestors (via mixins)
                    Object.defineProperty(shaders.uniforms, u, {
                        enumerable: true,
                        configurable: true,
                        get: function () {
                            // Uniform is explicitly defined on this style
                            if (shaders._uniforms[u] !== undefined) {
                                return shaders._uniforms[u];
                            }
                            // Uniform was mixed from another style, forward request there
                            // Identity check is needed to prevent infinite recursion if a previously defined uniform
                            // is set to undefined
                            else if (styles[shaders._uniform_scopes[u]].shaders.uniforms !== shaders.uniforms) {
                                return styles[shaders._uniform_scopes[u]].shaders.uniforms[u];
                            }
                            return undefined;
                        },
                        set: function (v) {
                            shaders._uniforms[u] = v;
                        }
                    });
                }
            });

        // Extensions: build a list of unique extensions
        shaders.extensions = Object.keys(shader_merges
            .map(x => x.extensions)
            .filter(x => x)
            .reduce((prev, cur) => {
                // single extension
                if (typeof cur === 'string') {
                    prev[cur] = true;
                }
                // array of extensions
                else {
                    cur.forEach(x => prev[x] = true);
                }
                return prev;
            }, {}) || {}
        );

        // Shader blocks
        // Mark all shader blocks for the target style as originating with its own name
        if (style.shaders && style.shaders.blocks) {
            style.shaders.block_scopes = style.shaders.block_scopes || {};
            for (let k in style.shaders.blocks) {
                let block = style.shaders.blocks[k];
                style.shaders.block_scopes[k] = style.shaders.block_scopes[k] || [];
                if (Array.isArray(block)) {
                    style.shaders.block_scopes[k].push(...block.map(() => style.name));
                }
                else {
                    style.shaders.block_scopes[k].push(style.name);
                }
            }
        }

        // Merge shader blocks, keeping track of which style each block originated from
        let mixed = {}; // all scopes mixed so far
        shader_merges.forEach(source => {
            if (!source.blocks) {
                return;
            }

            shaders.blocks = shaders.blocks || {};
            shaders.block_scopes = shaders.block_scopes || {};
            let mixed_source = {}; // scopes mixed for this source style

            for (let t in source.blocks) {
                let block = source.blocks[t];
                let block_scope = source.block_scopes[t];

                shaders.blocks[t] = shaders.blocks[t] || [];
                shaders.block_scopes[t] = shaders.block_scopes[t] || [];

                // standardize on arrays (block can be single or multi-value)
                block = Array.isArray(block) ? block : [block];
                block_scope = Array.isArray(block_scope) ? block_scope : [block_scope];

                for (let b=0; b < block.length; b++) {
                    // Skip blocks we've already mixed in from the same scope
                    // Repeating scope indicates a diamond pattern where a style is being mixed multiple times
                    if (mixed[block_scope[b]]) {
                        continue;
                    }
                    mixed_source[block_scope[b]] = true;

                    shaders.blocks[t].push(block[b]);
                    shaders.block_scopes[t].push(block_scope[b]);
                }
            }

            // Add styles mixed in from this source - they could be multi-level ancestors,
            // beyond the first-level "parents" defined in this style's `mix` list
            Object.assign(mixed, mixed_source);
        });

        Object.assign(style.mixed, mixed); // add all newly mixed styles

        style.shaders = shaders; // assign back to style
        return style;
    }

    // Create a new style
    // name: name of new style
    // config: properties of new style
    // styles: working set of styles being built (used for mixing in existing styles)
    create (name, config, styles = {}) {
        let style = mergeObjects({}, config); // deep copy
        style.name = name;

        // Style mixins
        style = this.mix(style, styles);

        // Has base style?
        // Only renderable (instantiated) styles should be included for run-time use
        // Others are intermediary/abstract, used during style composition but not execution
        if (style.base && this.base_styles[style.base]) {
            this.styles[name] = style = Object.assign(Object.create(this.base_styles[style.base]), style);
        }
        else {
            style.base = null; // null out invalid base style
        }

        return style;
    }

    // Called to create and initialize styles
    build (styles) {
        // Un-register existing styles from cross-thread communication
        if (this.styles) {
            Object.values(this.styles)
                .forEach(s => WorkerBroker.removeTarget(s.main_thread_target));
        }

        // Sort styles by dependency, then build them
        let style_deps = Object.keys(styles).sort(
            (a, b) => this.inheritanceDepth(a, styles) - this.inheritanceDepth(b, styles)
        );

        // Only keep built-in base styles
        for (let sname in this.styles) {
            if (!this.base_styles[sname]) {
                delete this.styles[sname];
            }
            else {
                this.styles[sname].reset();
            }
        }

        // Working set of styles being built
        let ws = {};
        style_deps.forEach(sname => {
            ws[sname] = this.create(sname, styles[sname], ws);
        });

        return this.styles;
    }

    // Initialize all styles
    initStyles (scene = {}) {
        // Initialize all
        for (let sname in this.styles) {
            this.styles[sname].init(scene);
        }
    }

    // Given a style key in a set of styles to add, count the length of the inheritance chain
    inheritanceDepth (key, styles) {
        let parents = 0;

        for (;;) {
            let style = styles[key];
            if (!style) {
                // this is a scene def error, trying to extend a style that doesn't exist
                break;
            }

            // Dependency chain ends when this style isn't mixing in any others
            if (!style.mix) {
                break;
            }

            // Traverse next parent style
            parents++;

            if (Array.isArray(style.mix)) {
                // If multiple mixins, find the deepest one
                parents += Math.max(...style.mix.map(s => {
                    // Trying to mix into itself!
                    if (key === s) {
                        return;
                    }

                    return this.inheritanceDepth(s, styles);
                }));
                break;
            }
            else {
                // Trying to mix into itself!
                if (key === style.mix) {
                    break;
                }

                // If single mixin, continue loop up the tree
                key = style.mix;
            }
        }
        return parents;
    }

}
<commit_msg>move line dash pattern reset to style manager destroy (avoid some errors from dash patterns destroyed while previous scene generation tiles still building in background)<commit_after>// Manage rendering styles
import ShaderProgram from '../gl/shader_program';
import mergeObjects from '../utils/merge';
import Geo from '../utils/geo';
import WorkerBroker from '../utils/worker_broker';
import log from '../utils/log';

import {Polygons} from './polygons/polygons';
import {Lines} from './lines/lines';
import {Points} from './points/points';
import {TextStyle} from './text/text';
import {RasterStyle} from './raster/raster';

import style_globals_source from './style_globals.glsl';
import selection_globals_source from '../selection/selection_globals.glsl';
import selection_vertex_source from '../selection/selection_vertex.glsl';

export class StyleManager {

    constructor () {
        this.styles = {};
        this.base_styles = {};

        // Add built-in rendering styles
        this.register(Object.create(Polygons));
        this.register(Object.create(Lines));
        this.register(Object.create(Points));
        this.register(Object.create(TextStyle));
        this.register(Object.create(RasterStyle));
    }

    // Global configuration for all styles
    init () {
        ShaderProgram.removeBlock('global');
        ShaderProgram.removeBlock('setup');

        // Model and world position accessors, layer re-ordering function
        ShaderProgram.addBlock('global', style_globals_source);

        // Feature selection global
        ShaderProgram.addBlock('global', selection_globals_source);

        // Feature selection vertex shader support
        ShaderProgram.replaceBlock('setup', selection_vertex_source);

        // Minimum value for float comparisons
        ShaderProgram.defines.TANGRAM_EPSILON = 0.00001;

        // Minimum depth buffer value separating each `order` unit
        // Assume min 16-bit depth buffer, in practice uses 14-bits, 1 extra bit to handle virtual half-layers
        // for outlines (inserted in between layers), another extra bit to prevent precision loss
        ShaderProgram.defines.TANGRAM_LAYER_DELTA = 1 / (1 << 14);

        // Internal tile scale
        ShaderProgram.defines.TANGRAM_TILE_SCALE =
            `vec3(${Geo.tile_scale}., ${Geo.tile_scale}., u_meters_per_pixel * ${Geo.tile_size}.)`;

        // Increases precision for height values
        ShaderProgram.defines.TANGRAM_HEIGHT_SCALE = Geo.height_scale;

        // Alpha discard threshold (substitute for alpha blending)
        ShaderProgram.defines.TANGRAM_ALPHA_TEST = 0.5;
    }

    // Destroy all styles for a given GL context
    destroy (gl) {
        Object.keys(this.styles).forEach((_name) => {
            let style = this.styles[_name];
            if (style.gl === gl) {
                log('trace', `StyleManager.destroy: destroying render style ${style.name}`);

                if (style.base) {
                    this.remove(style.name);
                }
                style.destroy();
            }
        });

        // Reset dash texture cache
        Lines.dash_textures = {};
    }

    // Register a style
    register (style) {
        this.styles[style.name] = style;
        this.base_styles[style.name] = style;
    }

    // Remove a style
    remove (name) {
        delete this.styles[name];
    }

    mix (style, styles) {
        // Exit early if we have already applied mixins to this style
        if (style.mixed) {
            return style;
        }
        style.mixed = {};

        // Mixin sources, in order
        let sources = [];
        if (style.mix) {
            if (Array.isArray(style.mix)) {
                sources.push(...style.mix);
            }
            else {
                sources.push(style.mix);
            }
            sources = sources.map(x => styles[x]).filter(x => x && x !== style); // TODO: warning on trying to mix into self

            // Track which styles were mixed into this one
            sources.forEach(s => style.mixed[s.name] = true);
        }
        sources.push(style);

        // Flags - OR'd, true if any style has it set
        style.animated = sources.some(x => x && x.animated);
        style.texcoords = sources.some(x => x && x.texcoords);

        // Overwrites - last definition wins
        style.base = sources.map(x => x.base).filter(x => x).pop();
        style.lighting = sources.map(x => x.lighting).filter(x => x != null).pop();
        style.texture = sources.map(x => x.texture).filter(x => x).pop();
        style.raster = sources.map(x => x.raster).filter(x => x != null).pop();
        style.dash = sources.map(x => x.dash).filter(x => x != null).pop();
        style.dash_background_color = sources.map(x => x.dash_background_color).filter(x => x != null).pop();
        if (sources.some(x => x.hasOwnProperty('blend') && x.blend)) {
            // only mix blend if explicitly set, otherwise let base style choose blending mode
            // hasOwnProperty check gives preference to base style prototype
            style.blend = sources.map(x => x.hasOwnProperty('blend') && x.blend).filter(x => x).pop();
        }
        style.blend_order = sources.map(x => x.blend_order).filter(x => x != null).pop();

        // Merges - property-specific rules for merging values
        style.defines = Object.assign({}, ...sources.map(x => x.defines).filter(x => x)); // internal defines (not user-defined)
        style.material = Object.assign({}, ...sources.map(x => x.material).filter(x => x));

        let draws = sources.map(x => x.draw).filter(x => x); // draw defaults
        if (draws.length > 0) {
            style.draw = mergeObjects({}, ...draws);
        }

        // Mix shader properties
        this.mixShaders(style, styles, sources);
        return style;
    }

    // Mix the propertes in the "shaders" block
    mixShaders (style, styles, sources) {
        let shaders = {}; // newly mixed shaders properties
        let shader_merges = sources.map(x => x.shaders).filter(x => x); // just the source styles with shader properties

        // Defines
        shaders.defines = Object.assign({}, ...shader_merges.map(x => x.defines).filter(x => x));

        // Uniforms
        shaders.uniforms = {};  // uniforms for this style, both explicitly defined, and mixed from other styles
        shaders._uniforms = (style.shaders && style.shaders.uniforms) || {}; // uniforms explicitly defined by *this* style
        shaders._uniform_scopes = {}; // tracks which style each uniform originated from (this one, or ancestor)

        // Mix in uniforms from ancestors, providing means to access
        sources
            .filter(x => x.shaders && x.shaders.uniforms)
            .forEach(x => {
                for (let u in x.shaders.uniforms) {
                    shaders._uniform_scopes[u] = x.name;

                    // Define getter and setter for this uniform
                    // Getter returns value for this style if present, otherwise asks appropriate ancestor for it
                    // Setter sets the value for this style (whether previously present in this style or not)
                    // Mimics JS prototype/hasOwnProperty behavior, but with multiple ancestors (via mixins)
                    Object.defineProperty(shaders.uniforms, u, {
                        enumerable: true,
                        configurable: true,
                        get: function () {
                            // Uniform is explicitly defined on this style
                            if (shaders._uniforms[u] !== undefined) {
                                return shaders._uniforms[u];
                            }
                            // Uniform was mixed from another style, forward request there
                            // Identity check is needed to prevent infinite recursion if a previously defined uniform
                            // is set to undefined
                            else if (styles[shaders._uniform_scopes[u]].shaders.uniforms !== shaders.uniforms) {
                                return styles[shaders._uniform_scopes[u]].shaders.uniforms[u];
                            }
                            return undefined;
                        },
                        set: function (v) {
                            shaders._uniforms[u] = v;
                        }
                    });
                }
            });

        // Extensions: build a list of unique extensions
        shaders.extensions = Object.keys(shader_merges
            .map(x => x.extensions)
            .filter(x => x)
            .reduce((prev, cur) => {
                // single extension
                if (typeof cur === 'string') {
                    prev[cur] = true;
                }
                // array of extensions
                else {
                    cur.forEach(x => prev[x] = true);
                }
                return prev;
            }, {}) || {}
        );

        // Shader blocks
        // Mark all shader blocks for the target style as originating with its own name
        if (style.shaders && style.shaders.blocks) {
            style.shaders.block_scopes = style.shaders.block_scopes || {};
            for (let k in style.shaders.blocks) {
                let block = style.shaders.blocks[k];
                style.shaders.block_scopes[k] = style.shaders.block_scopes[k] || [];
                if (Array.isArray(block)) {
                    style.shaders.block_scopes[k].push(...block.map(() => style.name));
                }
                else {
                    style.shaders.block_scopes[k].push(style.name);
                }
            }
        }

        // Merge shader blocks, keeping track of which style each block originated from
        let mixed = {}; // all scopes mixed so far
        shader_merges.forEach(source => {
            if (!source.blocks) {
                return;
            }

            shaders.blocks = shaders.blocks || {};
            shaders.block_scopes = shaders.block_scopes || {};
            let mixed_source = {}; // scopes mixed for this source style

            for (let t in source.blocks) {
                let block = source.blocks[t];
                let block_scope = source.block_scopes[t];

                shaders.blocks[t] = shaders.blocks[t] || [];
                shaders.block_scopes[t] = shaders.block_scopes[t] || [];

                // standardize on arrays (block can be single or multi-value)
                block = Array.isArray(block) ? block : [block];
                block_scope = Array.isArray(block_scope) ? block_scope : [block_scope];

                for (let b=0; b < block.length; b++) {
                    // Skip blocks we've already mixed in from the same scope
                    // Repeating scope indicates a diamond pattern where a style is being mixed multiple times
                    if (mixed[block_scope[b]]) {
                        continue;
                    }
                    mixed_source[block_scope[b]] = true;

                    shaders.blocks[t].push(block[b]);
                    shaders.block_scopes[t].push(block_scope[b]);
                }
            }

            // Add styles mixed in from this source - they could be multi-level ancestors,
            // beyond the first-level "parents" defined in this style's `mix` list
            Object.assign(mixed, mixed_source);
        });

        Object.assign(style.mixed, mixed); // add all newly mixed styles

        style.shaders = shaders; // assign back to style
        return style;
    }

    // Create a new style
    // name: name of new style
    // config: properties of new style
    // styles: working set of styles being built (used for mixing in existing styles)
    create (name, config, styles = {}) {
        let style = mergeObjects({}, config); // deep copy
        style.name = name;

        // Style mixins
        style = this.mix(style, styles);

        // Has base style?
        // Only renderable (instantiated) styles should be included for run-time use
        // Others are intermediary/abstract, used during style composition but not execution
        if (style.base && this.base_styles[style.base]) {
            this.styles[name] = style = Object.assign(Object.create(this.base_styles[style.base]), style);
        }
        else {
            style.base = null; // null out invalid base style
        }

        return style;
    }

    // Called to create and initialize styles
    build (styles) {
        // Un-register existing styles from cross-thread communication
        if (this.styles) {
            Object.values(this.styles)
                .forEach(s => WorkerBroker.removeTarget(s.main_thread_target));
        }

        // Sort styles by dependency, then build them
        let style_deps = Object.keys(styles).sort(
            (a, b) => this.inheritanceDepth(a, styles) - this.inheritanceDepth(b, styles)
        );

        // Only keep built-in base styles
        for (let sname in this.styles) {
            if (!this.base_styles[sname]) {
                delete this.styles[sname];
            }
            else {
                this.styles[sname].reset();
            }
        }

        // Working set of styles being built
        let ws = {};
        style_deps.forEach(sname => {
            ws[sname] = this.create(sname, styles[sname], ws);
        });

        return this.styles;
    }

    // Initialize all styles
    initStyles (scene = {}) {
        // Initialize all
        for (let sname in this.styles) {
            this.styles[sname].init(scene);
        }
    }

    // Given a style key in a set of styles to add, count the length of the inheritance chain
    inheritanceDepth (key, styles) {
        let parents = 0;

        for (;;) {
            let style = styles[key];
            if (!style) {
                // this is a scene def error, trying to extend a style that doesn't exist
                break;
            }

            // Dependency chain ends when this style isn't mixing in any others
            if (!style.mix) {
                break;
            }

            // Traverse next parent style
            parents++;

            if (Array.isArray(style.mix)) {
                // If multiple mixins, find the deepest one
                parents += Math.max(...style.mix.map(s => {
                    // Trying to mix into itself!
                    if (key === s) {
                        return;
                    }

                    return this.inheritanceDepth(s, styles);
                }));
                break;
            }
            else {
                // Trying to mix into itself!
                if (key === style.mix) {
                    break;
                }

                // If single mixin, continue loop up the tree
                key = style.mix;
            }
        }
        return parents;
    }

}
<|endoftext|>


<commit_before>import Colors from './colors';
import ColorManipulator from '../utils/color-manipulator';
import Extend from '../utils/extend';
import update from 'react-addons-update';

export default {

  //get the MUI theme corresponding to a raw theme
  getMuiTheme: function(rawTheme) {
    let returnObj = {
      appBar: {
        color: rawTheme.palette.primary1Color,
        textColor: rawTheme.palette.alternateTextColor,
        height: rawTheme.spacing.desktopKeylineIncrement,
      },
      avatar: {
        borderColor: 'rgba(0, 0, 0, 0.08)',
      },
      badge: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.textColor,
        primaryColor: rawTheme.palette.accent1Color,
        primaryTextColor: rawTheme.palette.alternateTextColor,
        secondaryColor: rawTheme.palette.primary1Color,
        secondaryTextColor: rawTheme.palette.alternateTextColor,
      },
      button: {
        height: 36,
        minWidth: 88,
        iconButtonSize: rawTheme.spacing.iconSize * 2,
      },
      cardText: {
        textColor: rawTheme.palette.textColor,
      },
      checkbox: {
        boxColor: rawTheme.palette.textColor,
        checkedColor: rawTheme.palette.primary1Color,
        requiredColor: rawTheme.palette.primary1Color,
        disabledColor: rawTheme.palette.disabledColor,
        labelColor: rawTheme.palette.textColor,
        labelDisabledColor: rawTheme.palette.disabledColor,
      },
      datePicker: {
        color: rawTheme.palette.primary1Color,
        textColor: rawTheme.palette.alternateTextColor,
        calendarTextColor: rawTheme.palette.textColor,
        selectColor: rawTheme.palette.primary2Color,
        selectTextColor: rawTheme.palette.alternateTextColor,
      },
      dropDownMenu: {
        accentColor: rawTheme.palette.borderColor,
      },
      flatButton: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.textColor,
        primaryTextColor: rawTheme.palette.accent1Color,
        secondaryTextColor: rawTheme.palette.primary1Color,
      },
      floatingActionButton: {
        buttonSize: 56,
        miniSize: 40,
        color: rawTheme.palette.accent1Color,
        iconColor: rawTheme.palette.alternateTextColor,
        secondaryColor: rawTheme.palette.primary1Color,
        secondaryIconColor: rawTheme.palette.alternateTextColor,
        disabledTextColor: rawTheme.palette.disabledColor,
      },
      gridTile: {
        textColor: Colors.white,
      },
      inkBar: {
        backgroundColor: rawTheme.palette.accent1Color,
      },
      leftNav: {
        width: rawTheme.spacing.desktopKeylineIncrement * 4,
        color: rawTheme.palette.canvasColor,
      },
      listItem: {
        nestedLevelDepth: 18,
      },
      menu: {
        backgroundColor: rawTheme.palette.canvasColor,
        containerBackgroundColor: rawTheme.palette.canvasColor,
      },
      menuItem: {
        dataHeight: 32,
        height: 48,
        hoverColor: 'rgba(0, 0, 0, .035)',
        padding: rawTheme.spacing.desktopGutter,
        selectedTextColor: rawTheme.palette.accent1Color,
      },
      menuSubheader: {
        padding: rawTheme.spacing.desktopGutter,
        borderColor: rawTheme.palette.borderColor,
        textColor: rawTheme.palette.primary1Color,
      },
      paper: {
        backgroundColor: rawTheme.palette.canvasColor,
      },
      radioButton: {
        borderColor:  rawTheme.palette.textColor,
        backgroundColor: rawTheme.palette.alternateTextColor,
        checkedColor: rawTheme.palette.primary1Color,
        requiredColor: rawTheme.palette.primary1Color,
        disabledColor: rawTheme.palette.disabledColor,
        size: 24,
        labelColor: rawTheme.palette.textColor,
        labelDisabledColor: rawTheme.palette.disabledColor,
      },
      raisedButton: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.textColor,
        primaryColor: rawTheme.palette.accent1Color,
        primaryTextColor: rawTheme.palette.alternateTextColor,
        secondaryColor: rawTheme.palette.primary1Color,
        secondaryTextColor: rawTheme.palette.alternateTextColor,
      },
      refreshIndicator: {
        strokeColor: rawTheme.palette.borderColor,
        loadingStrokeColor: rawTheme.palette.primary1Color,
      },
      slider: {
        trackSize: 2,
        trackColor: rawTheme.palette.primary3Color,
        trackColorSelected: rawTheme.palette.accent3Color,
        handleSize: 12,
        handleSizeDisabled: 8,
        handleSizeActive: 18,
        handleColorZero: rawTheme.palette.primary3Color,
        handleFillColor: rawTheme.palette.alternateTextColor,
        selectionColor: rawTheme.palette.primary1Color,
        rippleColor: rawTheme.palette.primary1Color,
      },
      snackbar: {
        textColor: rawTheme.palette.alternateTextColor,
        backgroundColor: rawTheme.palette.textColor,
        actionColor: rawTheme.palette.accent1Color,
      },
      table: {
        backgroundColor: rawTheme.palette.canvasColor,
      },
      tableHeader: {
        borderColor: rawTheme.palette.borderColor,
      },
      tableHeaderColumn: {
        textColor: rawTheme.palette.accent3Color,
        height: 56,
        spacing: 24,
      },
      tableFooter: {
        borderColor: rawTheme.palette.borderColor,
        textColor: rawTheme.palette.accent3Color,
      },
      tableRow: {
        hoverColor: rawTheme.palette.accent2Color,
        stripeColor: ColorManipulator.lighten(rawTheme.palette.primary1Color, 0.55),
        selectedColor: rawTheme.palette.borderColor,
        textColor: rawTheme.palette.textColor,
        borderColor: rawTheme.palette.borderColor,
      },
      tableRowColumn: {
        height: 48,
        spacing: 24,
      },
      timePicker: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.accent3Color,
        accentColor: rawTheme.palette.primary1Color,
        clockColor: rawTheme.palette.textColor,
        clockCircleColor: rawTheme.palette.clockCircleColor,
        headerColor: rawTheme.palette.pickerHeaderColor || rawTheme.palette.primary1Color,
        selectColor: rawTheme.palette.primary2Color,
        selectTextColor: rawTheme.palette.alternateTextColor,
      },
      toggle: {
        thumbOnColor: rawTheme.palette.primary1Color,
        thumbOffColor: rawTheme.palette.accent2Color,
        thumbDisabledColor: rawTheme.palette.borderColor,
        thumbRequiredColor: rawTheme.palette.primary1Color,
        trackOnColor: ColorManipulator.fade(rawTheme.palette.primary1Color, 0.5),
        trackOffColor: rawTheme.palette.primary3Color,
        trackDisabledColor: rawTheme.palette.primary3Color,
        labelColor: rawTheme.palette.textColor,
        labelDisabledColor: rawTheme.palette.disabledColor,
      },
      toolbar: {
        backgroundColor: ColorManipulator.darken(rawTheme.palette.accent2Color, 0.05),
        height: 56,
        titleFontSize: 20,
        iconColor: 'rgba(0, 0, 0, .40)',
        separatorColor: 'rgba(0, 0, 0, .175)',
        menuHoverColor: 'rgba(0, 0, 0, .10)',
      },
      tabs: {
        backgroundColor: rawTheme.palette.primary1Color,
        textColor: ColorManipulator.fade(rawTheme.palette.alternateTextColor, 0.6),
        selectedTextColor: rawTheme.palette.alternateTextColor,
      },
      textField: {
        textColor: rawTheme.palette.textColor,
        hintColor: rawTheme.palette.disabledColor,
        floatingLabelColor: rawTheme.palette.textColor,
        disabledTextColor: rawTheme.palette.disabledColor,
        errorColor: Colors.red500,
        focusColor: rawTheme.palette.primary1Color,
        backgroundColor: 'transparent',
        borderColor: rawTheme.palette.borderColor,
      },
      isRtl: false,
      zIndex: rawTheme.zIndex,
    };

    //add properties to objects inside 'returnObj' that depend on existing properties
    returnObj.flatButton.disabledTextColor = ColorManipulator.fade(returnObj.flatButton.textColor, 0.3);
    returnObj.raisedButton.disabledColor = ColorManipulator.darken(returnObj.raisedButton.color, 0.1);
    returnObj.raisedButton.disabledTextColor = ColorManipulator.fade(returnObj.raisedButton.textColor, 0.3);
    returnObj.toggle.trackRequiredColor = ColorManipulator.fade(returnObj.toggle.thumbRequiredColor, 0.5);

    //append the raw theme object to 'returnObj'
    returnObj.rawTheme = rawTheme;

    //set 'static' key as true (by default) on return object. This is to support the ContextPure mixin.
    returnObj.static = true;

    return returnObj;
  },

  //functions to modify properties of raw theme, namely spacing, palette
  //and font family. These functions use the React update immutability helper
  //to create a new object for the raw theme, and return a new MUI theme object

  //function to modify the spacing of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new theme.
  modifyRawThemeSpacing: function(muiTheme, newSpacing) {
    let newRawTheme = update(muiTheme.rawTheme, {spacing: {$set: newSpacing}});
    return this.getMuiTheme(newRawTheme);
  },

  //function to modify the palette of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new raw theme.
  //keys inside 'newPalette' override values for existing keys in palette
  modifyRawThemePalette: function(muiTheme, newPaletteKeys) {
    let newPalette = Extend(muiTheme.rawTheme.palette, newPaletteKeys);
    let newRawTheme = update(muiTheme.rawTheme, {palette: {$set: newPalette}});
    return this.getMuiTheme(newRawTheme);
  },

  //function to modify the font family of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new raw theme.
  modifyRawThemeFontFamily: function(muiTheme, newFontFamily) {
    let newRawTheme = update(muiTheme.rawTheme, {fontFamily: {$set: newFontFamily}});
    return this.getMuiTheme(newRawTheme);
  },

};
<commit_msg>Update theme-manager.js<commit_after>import Colors from './colors';
import ColorManipulator from '../utils/color-manipulator';
import Extend from '../utils/extend';
import update from 'react-addons-update';

export default {

  //get the MUI theme corresponding to a raw theme
  getMuiTheme: function(rawTheme) {
    let returnObj = {
      appBar: {
        color: rawTheme.palette.primary1Color,
        textColor: rawTheme.palette.alternateTextColor,
        height: rawTheme.spacing.desktopKeylineIncrement,
      },
      avatar: {
        borderColor: 'rgba(0, 0, 0, 0.08)',
      },
      badge: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.textColor,
        primaryColor: rawTheme.palette.accent1Color,
        primaryTextColor: rawTheme.palette.alternateTextColor,
        secondaryColor: rawTheme.palette.primary1Color,
        secondaryTextColor: rawTheme.palette.alternateTextColor,
      },
      button: {
        height: 36,
        minWidth: 88,
        iconButtonSize: rawTheme.spacing.iconSize * 2,
      },
      cardText: {
        textColor: rawTheme.palette.textColor,
      },
      checkbox: {
        boxColor: rawTheme.palette.textColor,
        checkedColor: rawTheme.palette.primary1Color,
        requiredColor: rawTheme.palette.primary1Color,
        disabledColor: rawTheme.palette.disabledColor,
        labelColor: rawTheme.palette.textColor,
        labelDisabledColor: rawTheme.palette.disabledColor,
      },
      datePicker: {
        color: rawTheme.palette.primary1Color,
        textColor: rawTheme.palette.alternateTextColor,
        calendarTextColor: rawTheme.palette.textColor,
        selectColor: rawTheme.palette.primary2Color,
        selectTextColor: rawTheme.palette.alternateTextColor,
      },
      dropDownMenu: {
        accentColor: rawTheme.palette.borderColor,
      },
      flatButton: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.textColor,
        primaryTextColor: rawTheme.palette.accent1Color,
        secondaryTextColor: rawTheme.palette.primary1Color,
      },
      floatingActionButton: {
        buttonSize: 56,
        miniSize: 40,
        color: rawTheme.palette.accent1Color,
        iconColor: rawTheme.palette.alternateTextColor,
        secondaryColor: rawTheme.palette.primary1Color,
        secondaryIconColor: rawTheme.palette.alternateTextColor,
        disabledTextColor: rawTheme.palette.disabledColor,
      },
      gridTile: {
        textColor: Colors.white,
      },
      inkBar: {
        backgroundColor: rawTheme.palette.accent1Color,
      },
      leftNav: {
        width: rawTheme.spacing.desktopKeylineIncrement * 4,
        color: rawTheme.palette.canvasColor,
      },
      listItem: {
        nestedLevelDepth: 18,
      },
      menu: {
        backgroundColor: rawTheme.palette.canvasColor,
        containerBackgroundColor: rawTheme.palette.canvasColor,
      },
      menuItem: {
        dataHeight: 32,
        height: 48,
        hoverColor: 'rgba(0, 0, 0, .035)',
        padding: rawTheme.spacing.desktopGutter,
        selectedTextColor: rawTheme.palette.accent1Color,
      },
      menuSubheader: {
        padding: rawTheme.spacing.desktopGutter,
        borderColor: rawTheme.palette.borderColor,
        textColor: rawTheme.palette.primary1Color,
      },
      paper: {
        backgroundColor: rawTheme.palette.canvasColor,
      },
      radioButton: {
        borderColor:  rawTheme.palette.textColor,
        backgroundColor: rawTheme.palette.alternateTextColor,
        checkedColor: rawTheme.palette.primary1Color,
        requiredColor: rawTheme.palette.primary1Color,
        disabledColor: rawTheme.palette.disabledColor,
        size: 24,
        labelColor: rawTheme.palette.textColor,
        labelDisabledColor: rawTheme.palette.disabledColor,
      },
      raisedButton: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.textColor,
        primaryColor: rawTheme.palette.accent1Color,
        primaryTextColor: rawTheme.palette.alternateTextColor,
        secondaryColor: rawTheme.palette.primary1Color,
        secondaryTextColor: rawTheme.palette.alternateTextColor,
      },
      refreshIndicator: {
        strokeColor: rawTheme.palette.borderColor,
        loadingStrokeColor: rawTheme.palette.primary1Color,
      },
      slider: {
        trackSize: 2,
        trackColor: rawTheme.palette.primary3Color,
        trackColorSelected: rawTheme.palette.accent3Color,
        handleSize: 12,
        handleSizeDisabled: 8,
        handleSizeActive: 18,
        handleColorZero: rawTheme.palette.primary3Color,
        handleFillColor: rawTheme.palette.alternateTextColor,
        selectionColor: rawTheme.palette.primary1Color,
        rippleColor: rawTheme.palette.primary1Color,
      },
      snackbar: {
        textColor: rawTheme.palette.alternateTextColor,
        backgroundColor: rawTheme.palette.textColor,
        actionColor: rawTheme.palette.accent1Color,
      },
      table: {
        backgroundColor: rawTheme.palette.canvasColor,
      },
      tableHeader: {
        borderColor: rawTheme.palette.borderColor,
      },
      tableHeaderColumn: {
        textColor: rawTheme.palette.accent3Color,
        height: 56,
        spacing: 24,
      },
      tableFooter: {
        borderColor: rawTheme.palette.borderColor,
        textColor: rawTheme.palette.accent3Color,
      },
      tableRow: {
        hoverColor: rawTheme.palette.accent2Color,
        stripeColor: ColorManipulator.lighten(rawTheme.palette.primary1Color, 0.55),
        selectedColor: rawTheme.palette.borderColor,
        textColor: rawTheme.palette.textColor,
        borderColor: rawTheme.palette.borderColor,
      },
      tableRowColumn: {
        height: 48,
        spacing: 24,
      },
      timePicker: {
        color: rawTheme.palette.alternateTextColor,
        textColor: rawTheme.palette.accent3Color,
        accentColor: rawTheme.palette.primary1Color,
        clockColor: rawTheme.palette.textColor,
        clockCircleColor: rawTheme.palette.clockCircleColor,
        headerColor: rawTheme.palette.pickerHeaderColor || rawTheme.palette.primary1Color,
        selectColor: rawTheme.palette.primary2Color,
        selectTextColor: rawTheme.palette.alternateTextColor,
      },
      toggle: {
        thumbOnColor: rawTheme.palette.primary1Color,
        thumbOffColor: rawTheme.palette.accent2Color,
        thumbDisabledColor: rawTheme.palette.borderColor,
        thumbRequiredColor: rawTheme.palette.primary1Color,
        trackOnColor: ColorManipulator.fade(rawTheme.palette.primary1Color, 0.5),
        trackOffColor: rawTheme.palette.primary3Color,
        trackDisabledColor: rawTheme.palette.primary3Color,
        labelColor: rawTheme.palette.textColor,
        labelDisabledColor: rawTheme.palette.disabledColor,
      },
      toolbar: {
        backgroundColor: ColorManipulator.darken(rawTheme.palette.accent2Color, 0.05),
        height: 56,
        titleFontSize: 20,
        iconColor: 'rgba(0, 0, 0, .40)',
        separatorColor: 'rgba(0, 0, 0, .175)',
        menuHoverColor: 'rgba(0, 0, 0, .10)',
      },
      tabs: {
        backgroundColor: rawTheme.palette.primary1Color,
        textColor: ColorManipulator.fade(rawTheme.palette.alternateTextColor, 0.6),
        selectedTextColor: rawTheme.palette.alternateTextColor,
      },
      textField: {
        textColor: rawTheme.palette.textColor,
        hintColor: rawTheme.palette.disabledColor,
        floatingLabelColor: rawTheme.palette.textColor,
        disabledTextColor: rawTheme.palette.disabledColor,
        errorColor: Colors.red500,
        focusColor: rawTheme.palette.primary1Color,
        backgroundColor: 'transparent',
        borderColor: rawTheme.palette.borderColor,
      },
      isRtl: false,
      zIndex: rawTheme.zIndex,
    };

    //add properties to objects inside 'returnObj' that depend on existing properties
    returnObj.flatButton.disabledTextColor = ColorManipulator.fade(returnObj.flatButton.textColor, 0.3);
    returnObj.raisedButton.disabledColor = ColorManipulator.darken(returnObj.raisedButton.color, 0.1);
    returnObj.raisedButton.disabledTextColor = ColorManipulator.fade(returnObj.raisedButton.textColor, 0.3);
    returnObj.toggle.trackRequiredColor = ColorManipulator.fade(returnObj.toggle.thumbRequiredColor, 0.5);

    //append the raw theme object to 'returnObj'
    returnObj.rawTheme = rawTheme;

    //set 'static' key as true (by default) on return object. This is to support the ContextPure mixin.
    returnObj.static = true;

    return returnObj;
  },

  //functions to modify properties of raw theme, namely spacing, palette
  //and font family. These functions use the React update immutability helper
  //to create a new object for the raw theme, and return a new MUI theme object

  //function to modify the spacing of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new theme.
  modifyRawThemeSpacing: function(muiTheme, newSpacing) {
    let newRawTheme = update(muiTheme.rawTheme, {spacing: {$set: newSpacing}});
    return this.getMuiTheme(newRawTheme);
  },

  //function to modify the palette of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new raw theme.
  //keys inside 'newPalette' override values for existing keys in palette
  modifyRawThemePalette: function(muiTheme, newPaletteKeys) {
    let newPalette = Extend(muiTheme.rawTheme.palette, newPaletteKeys);
    let newRawTheme = update(muiTheme.rawTheme, {palette: {$set: newPalette}});
    return this.getMuiTheme(newRawTheme);
  },

  //function to modify the font family of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new raw theme.
  modifyRawThemeFontFamily: function(muiTheme, newFontFamily) {
    let newRawTheme = update(muiTheme.rawTheme, {fontFamily: {$set: newFontFamily}});
    return this.getMuiTheme(newRawTheme);
  },

  //function to modify the zIndex of the raw theme. This function recomputes
  //the MUI theme and returns it based on the new raw theme.
  modifyRawThemePalette: function(muiTheme, newZIndexKeys) {
    let newZIndex = Extend(muiTheme.rawTheme.zIndex, newZIndexKeys);
    let newRawTheme = update(muiTheme.rawTheme, {zIndex: {$set: newZIndex}});
    return this.getMuiTheme(newRawTheme);
  },

};
<|endoftext|>


<commit_before>/* @flow strict-local */
import type { Style } from '../types';

export type UtilityStyles = {
  padding: Style,
  paddingVertical: Style,
  paddingHorizontal: Style,
  paddingTop: Style,
  paddingBottom: Style,
  paddingLeft: Style,
  paddingRight: Style,
  halfPadding: Style,
  halfPaddingVertical: Style,
  halfPaddingHorizontal: Style,
  halfPaddingTop: Style,
  halfPaddingBottom: Style,
  halfPaddingLeft: Style,
  halfPaddingRight: Style,
  margin: Style,
  marginVertical: Style,
  marginHorizontal: Style,
  marginTop: Style,
  marginBottom: Style,
  marginLeft: Style,
  marginRight: Style,
  halfMargin: Style,
  halfMarginVertical: Style,
  halfMarginHorizontal: Style,
  halfMarginTop: Style,
  halfMarginBottom: Style,
  halfMarginLeft: Style,
  halfMarginRight: Style,
};

export default {
  // Padding
  padding: {
    padding: 16,
  },
  paddingVertical: {
    paddingVertical: 16,
  },
  paddingHorizontal: {
    paddingHorizontal: 16,
  },
  paddingTop: {
    paddingTop: 16,
  },
  paddingBottom: {
    paddingBottom: 16,
  },
  paddingLeft: {
    paddingLeft: 16,
  },
  paddingRight: {
    paddingRight: 16,
  },
  // Half padding
  halfPadding: {
    padding: 8,
  },
  halfPaddingVertical: {
    paddingVertical: 8,
  },
  halfPaddingHorizontal: {
    paddingHorizontal: 8,
  },
  halfPaddingTop: {
    paddingTop: 8,
  },
  halfPaddingBottom: {
    paddingBottom: 8,
  },
  halfPaddingLeft: {
    paddingLeft: 8,
  },
  halfPaddingRight: {
    paddingRight: 8,
  },
  // Margin
  margin: {
    margin: 16,
  },
  marginVertical: {
    marginVertical: 16,
  },
  marginHorizontal: {
    marginHorizontal: 16,
  },
  marginTop: {
    marginTop: 16,
  },
  marginBottom: {
    marginBottom: 16,
  },
  marginLeft: {
    marginLeft: 16,
  },
  marginRight: {
    marginRight: 16,
  },
  // Half margin
  halfMargin: {
    margin: 8,
  },
  halfMarginVertical: {
    marginVertical: 8,
  },
  halfMarginHorizontal: {
    marginHorizontal: 8,
  },
  halfMarginTop: {
    marginTop: 8,
  },
  halfMarginBottom: {
    marginBottom: 8,
  },
  halfMarginLeft: {
    marginLeft: 8,
  },
  halfMarginRight: {
    marginRight: 8,
  },
};
<commit_msg>styles: Delete one straggler boilerplate-type.<commit_after>/* @flow strict */

export default {
  // Padding
  padding: {
    padding: 16,
  },
  paddingVertical: {
    paddingVertical: 16,
  },
  paddingHorizontal: {
    paddingHorizontal: 16,
  },
  paddingTop: {
    paddingTop: 16,
  },
  paddingBottom: {
    paddingBottom: 16,
  },
  paddingLeft: {
    paddingLeft: 16,
  },
  paddingRight: {
    paddingRight: 16,
  },
  // Half padding
  halfPadding: {
    padding: 8,
  },
  halfPaddingVertical: {
    paddingVertical: 8,
  },
  halfPaddingHorizontal: {
    paddingHorizontal: 8,
  },
  halfPaddingTop: {
    paddingTop: 8,
  },
  halfPaddingBottom: {
    paddingBottom: 8,
  },
  halfPaddingLeft: {
    paddingLeft: 8,
  },
  halfPaddingRight: {
    paddingRight: 8,
  },
  // Margin
  margin: {
    margin: 16,
  },
  marginVertical: {
    marginVertical: 16,
  },
  marginHorizontal: {
    marginHorizontal: 16,
  },
  marginTop: {
    marginTop: 16,
  },
  marginBottom: {
    marginBottom: 16,
  },
  marginLeft: {
    marginLeft: 16,
  },
  marginRight: {
    marginRight: 16,
  },
  // Half margin
  halfMargin: {
    margin: 8,
  },
  halfMarginVertical: {
    marginVertical: 8,
  },
  halfMarginHorizontal: {
    marginHorizontal: 8,
  },
  halfMarginTop: {
    marginTop: 8,
  },
  halfMarginBottom: {
    marginBottom: 8,
  },
  halfMarginLeft: {
    marginLeft: 8,
  },
  halfMarginRight: {
    marginRight: 8,
  },
};
<|endoftext|>