diff --git a/package-lock.json b/package-lock.json
index 7c622128d..e9a357e9e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
"babel-polyfill": "6.26.0",
"classnames": "2.2.6",
"lodash.debounce": "4.0.8",
+ "lodash.snakecase": "^4.1.1",
"moment": "2.29.1",
"prop-types": "15.7.2",
"react": "16.14.0",
diff --git a/package.json b/package.json
index 2918d2e91..fd8f1a0c2 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"babel-polyfill": "6.26.0",
"classnames": "2.2.6",
"lodash.debounce": "4.0.8",
+ "lodash.snakecase": "^4.1.1",
"moment": "2.29.1",
"prop-types": "15.7.2",
"react": "16.14.0",
diff --git a/src/Configuration/Provisioning/Dashboard.jsx b/src/Configuration/Provisioning/Dashboard.jsx
index c9539b90e..7ccefcf8d 100644
--- a/src/Configuration/Provisioning/Dashboard.jsx
+++ b/src/Configuration/Provisioning/Dashboard.jsx
@@ -4,7 +4,7 @@ import { v4 as uuidv4 } from 'uuid';
import DashboardHeader from './DashboardHeader';
import DashboardToast from './DashboardToast';
-import DashboardDatatable from './DashboardDatatable';
+import DashboardDataTable from './DashboardDataTable';
import { toastText } from './data/constants';
// TODO: Create a new item header, search box and datatable
@@ -29,7 +29,7 @@ const Dashboard = () => {
return (
<>
-
+
{toasts.map(({ text, uuid }) => ())}
>
);
diff --git a/src/Configuration/Provisioning/DashboardDatatable/DashboardDatatable.jsx b/src/Configuration/Provisioning/DashboardDataTable/DashboardDataTable.jsx
similarity index 90%
rename from src/Configuration/Provisioning/DashboardDatatable/DashboardDatatable.jsx
rename to src/Configuration/Provisioning/DashboardDataTable/DashboardDataTable.jsx
index 00f0b2d8e..3ce995bb7 100644
--- a/src/Configuration/Provisioning/DashboardDatatable/DashboardDatatable.jsx
+++ b/src/Configuration/Provisioning/DashboardDataTable/DashboardDataTable.jsx
@@ -1,10 +1,5 @@
-import {
- DataTable,
- TextFilter,
-} from '@edx/paragon';
-import React, {
- useCallback, useMemo, useState,
-} from 'react';
+import { DataTable, TextFilter } from '@edx/paragon';
+import React, { useCallback, useMemo, useState } from 'react';
import { useContextSelector } from 'use-context-selector';
import debounce from 'lodash.debounce';
import { logError } from '@edx/frontend-platform/logging';
@@ -13,9 +8,9 @@ import { MAX_PAGE_SIZE } from '../data/constants';
import { useDashboardContext } from '../data/hooks';
import DashboardTableActions from './DashboardTableActions';
import DashboardTableBadges from './DashboardTableBadges';
-import { filterDatatableData, sortDatatableData, transformDatatableDate } from '../data/utils';
+import { filterDatatableData, sortDataTableData, transformDatatableDate } from '../data/utils';
-const DashboardDatatable = () => {
+const DashboardDataTable = () => {
const { enterpriseSubsidies } = useContextSelector(DashboardContext, v => v[0]);
const { hydrateEnterpriseSubsidies } = useDashboardContext();
const [isLoading, setIsLoading] = useState(true);
@@ -25,10 +20,11 @@ const DashboardDatatable = () => {
const fetchData = useCallback(async (datatableProps) => {
setIsLoading(true);
+ console.log(datatableProps.sortBy);
try {
await hydrateEnterpriseSubsidies({
pageIndex: datatableProps.pageIndex + 1,
- sortBy: sortDatatableData(datatableProps),
+ sortBy: sortDataTableData(datatableProps),
filterBy: filterDatatableData(datatableProps),
});
} catch (e) {
@@ -111,4 +107,4 @@ const DashboardDatatable = () => {
);
};
-export default DashboardDatatable;
+export default DashboardDataTable;
diff --git a/src/Configuration/Provisioning/DashboardDatatable/DashboardTableActions.jsx b/src/Configuration/Provisioning/DashboardDataTable/DashboardTableActions.jsx
similarity index 57%
rename from src/Configuration/Provisioning/DashboardDatatable/DashboardTableActions.jsx
rename to src/Configuration/Provisioning/DashboardDataTable/DashboardTableActions.jsx
index ee6106f2b..a37daac0f 100644
--- a/src/Configuration/Provisioning/DashboardDatatable/DashboardTableActions.jsx
+++ b/src/Configuration/Provisioning/DashboardDataTable/DashboardTableActions.jsx
@@ -17,8 +17,8 @@ const DashboardTableActions = ({ row }) => {
const { DJANGO_ADMIN_SUBSIDY_BASE_URL } = getConfig();
const history = useHistory();
const { HOME } = ROUTES.CONFIGURATION.SUB_DIRECTORY.PROVISIONING;
- return [
- getConfig().FEATURE_CONFIGURATION_EDIT_ENTERPRISE_PROVISION && (
+ const enabledActionArray = [{
+ action: (
{
data-testid={`Edit-${rowUuid}`}
/>
),
-
-
- ,
- ];
+ enabled: getConfig().FEATURE_CONFIGURATION_EDIT_ENTERPRISE_PROVISION,
+ }, {
+ action: (
+
+
+ ),
+ enabled: true,
+ }].filter(interaction => interaction.enabled);
+
+ return enabledActionArray.map(interaction => interaction.action);
};
DashboardTableActions.propTypes = {
diff --git a/src/Configuration/Provisioning/DashboardDatatable/DashboardTableBadges.jsx b/src/Configuration/Provisioning/DashboardDataTable/DashboardTableBadges.jsx
similarity index 100%
rename from src/Configuration/Provisioning/DashboardDatatable/DashboardTableBadges.jsx
rename to src/Configuration/Provisioning/DashboardDataTable/DashboardTableBadges.jsx
diff --git a/src/Configuration/Provisioning/DashboardDataTable/index.js b/src/Configuration/Provisioning/DashboardDataTable/index.js
new file mode 100644
index 000000000..582d9be22
--- /dev/null
+++ b/src/Configuration/Provisioning/DashboardDataTable/index.js
@@ -0,0 +1,3 @@
+import DashboardDataTable from './DashboardDataTable';
+
+export default DashboardDataTable;
diff --git a/src/Configuration/Provisioning/DashboardDatatable/tests/DashboardDatatable.test.jsx b/src/Configuration/Provisioning/DashboardDataTable/tests/DashboardDataTable.test.jsx
similarity index 95%
rename from src/Configuration/Provisioning/DashboardDatatable/tests/DashboardDatatable.test.jsx
rename to src/Configuration/Provisioning/DashboardDataTable/tests/DashboardDataTable.test.jsx
index d1a5d0ef9..c7884c763 100644
--- a/src/Configuration/Provisioning/DashboardDatatable/tests/DashboardDatatable.test.jsx
+++ b/src/Configuration/Provisioning/DashboardDataTable/tests/DashboardDataTable.test.jsx
@@ -3,7 +3,7 @@ import { renderWithRouter } from '@edx/frontend-enterprise-utils';
import { screen, waitFor } from '@testing-library/react';
import { camelCaseObject } from '@edx/frontend-platform';
import { DashboardContext, initialStateValue } from '../../../testData/Dashboard';
-import DashboardDatatable from '../DashboardDatatable';
+import DashboardDataTable from '../DashboardDataTable';
import { sampleDataTableData } from '../../../testData/constants';
// Mock the debounce function
@@ -32,7 +32,7 @@ const DashboardDatatableWrapper = ({
value = initialStateValue,
}) => (
-
+
);
diff --git a/src/Configuration/Provisioning/DashboardDatatable/tests/DashboardTableActions.test.jsx b/src/Configuration/Provisioning/DashboardDataTable/tests/DashboardTableActions.test.jsx
similarity index 100%
rename from src/Configuration/Provisioning/DashboardDatatable/tests/DashboardTableActions.test.jsx
rename to src/Configuration/Provisioning/DashboardDataTable/tests/DashboardTableActions.test.jsx
diff --git a/src/Configuration/Provisioning/DashboardDatatable/tests/DashboardTableBadges.test.jsx b/src/Configuration/Provisioning/DashboardDataTable/tests/DashboardTableBadges.test.jsx
similarity index 100%
rename from src/Configuration/Provisioning/DashboardDatatable/tests/DashboardTableBadges.test.jsx
rename to src/Configuration/Provisioning/DashboardDataTable/tests/DashboardTableBadges.test.jsx
diff --git a/src/Configuration/Provisioning/DashboardDatatable/index.js b/src/Configuration/Provisioning/DashboardDatatable/index.js
deleted file mode 100644
index c9fbd2630..000000000
--- a/src/Configuration/Provisioning/DashboardDatatable/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import DashboardDatatable from './DashboardDatatable';
-
-export default DashboardDatatable;
diff --git a/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormCustomer.jsx b/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormCustomer.jsx
index 8df0a8503..374c658e7 100644
--- a/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormCustomer.jsx
+++ b/src/Configuration/Provisioning/ProvisioningForm/ProvisioningFormCustomer.jsx
@@ -54,9 +54,9 @@ const ProvisioningFormCustomer = () => {
data-testid="customer-financial-identifier"
/>
{isOpportunityProduct && (
-
- {financialIdentifier.length}/{CUSTOMER.FINANCIAL_IDENTIFIER.MAX_LENGTH}
-
+
+ {financialIdentifier.length}/{CUSTOMER.FINANCIAL_IDENTIFIER.MAX_LENGTH}
+
)}
{!isOpportunityProduct && (
{
describe('sortDatatableData', () => {
it('returns null if no data is passed', () => {
const output = null;
- expect(sortDatatableData({ sortBy: {} })).toEqual(output);
+ expect(sortDataTableData({ sortBy: {} })).toEqual(output);
});
it('returns a sort by expirationDateTime if isActive is passed as the id', () => {
const output = 'expirationDatetime';
// desc is true
- expect(sortDatatableData({
+ expect(sortDataTableData({
sortBy:
[{
id: 'isActive',
@@ -387,7 +387,7 @@ describe('sortDatatableData', () => {
})).toEqual(`-${output}`);
// desc is false
- expect(sortDatatableData({
+ expect(sortDataTableData({
sortBy:
[{
id: 'isActive',
@@ -399,7 +399,7 @@ describe('sortDatatableData', () => {
const output = 'title';
// desc is true
- expect(sortDatatableData({
+ expect(sortDataTableData({
sortBy:
[{
id: 'title',
@@ -408,7 +408,7 @@ describe('sortDatatableData', () => {
})).toEqual(`-${output}`);
// desc is false
- expect(sortDatatableData({
+ expect(sortDataTableData({
sortBy:
[{
id: 'title',
diff --git a/src/Configuration/Provisioning/data/utils.js b/src/Configuration/Provisioning/data/utils.js
index d9d314aff..1133d112a 100644
--- a/src/Configuration/Provisioning/data/utils.js
+++ b/src/Configuration/Provisioning/data/utils.js
@@ -246,10 +246,7 @@ export function getCamelCasedConfigAttribute(attribute) {
*/
export function normalizeSubsidyDataTableData({ fetchedSubsidyData, fetchedCustomerData }) {
if (fetchedSubsidyData.count === 0) {
- return {
- ...fetchedSubsidyData,
- results: [],
- };
+ return fetchedSubsidyData;
}
const normalizedData = fetchedSubsidyData.results.map((item) => {
const {
@@ -453,10 +450,10 @@ export function generatePolicyName(formData, index) {
* @returns - Returns a date string in the format of MM-DD-YYYY
*/
export function transformDatatableDate(date) {
- if (date) {
- return new Date(date).toLocaleDateString().replace(/\//g, '-');
+ if (!date) {
+ return null;
}
- return null;
+ return new Date(date).toLocaleDateString().replace(/\//g, '-');
}
/**
@@ -479,14 +476,15 @@ export function filterDatatableData({ filters }) {
* @param {Object} sortBy - The sort object from the datatable
* @returns - Returns a string that can be used to sort the API response
*/
-export function sortDatatableData({ sortBy }) {
- if (sortBy[0]?.id) {
- if (sortBy[0].id === 'isActive') {
- return sortBy[0].desc ? '-expirationDatetime' : 'expirationDatetime';
- }
- return sortBy[0].desc ? `-${sortBy[0].id}` : sortBy[0].id;
+export function sortDataTableData({ sortBy }) {
+ const sortByObject = sortBy[0];
+ if (!sortByObject) {
+ return null;
}
- return null;
+ if (sortByObject.id === 'isActive') {
+ return sortByObject.desc ? '-expirationDatetime' : 'expirationDatetime';
+ }
+ return sortByObject.desc ? `-${sortByObject.id}` : sortByObject.id;
}
/**
diff --git a/src/data/services/SubsidyApiService.js b/src/data/services/SubsidyApiService.js
index d22146ebd..26dc0bb75 100644
--- a/src/data/services/SubsidyApiService.js
+++ b/src/data/services/SubsidyApiService.js
@@ -1,25 +1,23 @@
-import { getConfig } from '@edx/frontend-platform';
+import { getConfig, snakeCaseObject } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
-import { snakeCaseWord } from '../../utils';
+import snakeCase from 'lodash.snakecase';
class SubsidyApiService {
static apiClient = getAuthenticatedHttpClient;
static getAllSubsidies = ({
- paginatedURL,
+ pageIndex,
pageSize,
sortBy,
filteredData,
}) => {
const subsidiesURL = `${getConfig().SUBSIDY_BASE_URL}/api/v1/subsidies/`;
- let optionalUrlParams = '';
-
- optionalUrlParams += pageSize ? `&page_size=${pageSize}` : '';
- optionalUrlParams += sortBy ? `&sort_by=${snakeCaseWord(sortBy)}` : '';
- Object.keys(filteredData).forEach((key) => {
- optionalUrlParams += `&${snakeCaseWord(key)}=${filteredData[key]}`;
- });
- return SubsidyApiService.apiClient().get(`${subsidiesURL}?page=${paginatedURL}${optionalUrlParams}`);
+ const optionalUrlParams = new URLSearchParams(snakeCaseObject({
+ pageSize,
+ sortBy: sortBy ? snakeCase(sortBy) : 'uuid',
+ ...filteredData,
+ })).toString();
+ return SubsidyApiService.apiClient().get(`${subsidiesURL}?page=${pageIndex}&${optionalUrlParams}`);
};
static postSubsidy = (
diff --git a/src/utils/index.js b/src/utils/index.js
index 62b24a4a4..c2d921d44 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -44,16 +44,16 @@ export const isWholeDollarAmount = (value) => Boolean(value && value.match(DIGIT
// Opportunity Product must begin with 00k and be 18 alphanumeric characters long
export const isValidOpportunityProduct = value => {
+ if (!value) {
+ return false;
+ }
if (value?.length <= 2) {
return Boolean(value && value.match(/^0{1,2}$/));
}
if (value?.length === 3) {
return Boolean(value && value.match(/^0{2}k$/));
}
- if (value?.length > 3 || value?.length < 19) {
- return Boolean(value && value.match(/^0{2}k([0-9A-Za-z]{1,15})$/));
- }
- return false;
+ return Boolean(value && value.match(/^0{2}k([0-9A-Za-z]{1,15})$/));
};
export function sort(firstElement, secondElement, key, direction) {
@@ -73,16 +73,6 @@ export function titleCase(str) {
return str.toLowerCase().replace(/_/g, ' ').replace(/\b(\w)/g, s => s.toUpperCase());
}
-/**
- * Convert a string containing camelCase into snake_case.
- * @param {String} word - word to be converted to snake_case
- * @returns - snake_case word
- */
-export function snakeCaseWord(word) {
- const result = word.replace(/([A-Z])/g, ' $1');
- return result.split(' ').join('_').toLowerCase();
-}
-
/** Compare dates function for array.sort() */
export function sortedCompareDates(x, y, asc) {
const a = new Date(x);
diff --git a/src/utils/index.test.js b/src/utils/index.test.js
index 972aa8f46..8ed686690 100644
--- a/src/utils/index.test.js
+++ b/src/utils/index.test.js
@@ -1,20 +1,19 @@
import {
- isEmail,
- isValidUsername,
- isValidLMSUserID,
+ extractMessageTuple,
+ extractParams,
formatBoolean,
formatDate,
formatUnixTimestamp,
- sort,
- titleCase,
- sortedCompareDates,
+ isEmail,
isValidCourseID,
- extractMessageTuple,
- extractParams,
isValidDateString,
- isWholeDollarAmount,
+ isValidLMSUserID,
isValidOpportunityProduct,
- snakeCaseWord,
+ isValidUsername,
+ isWholeDollarAmount,
+ sort,
+ sortedCompareDates,
+ titleCase,
} from './index';
describe('Test Utils', () => {
@@ -276,10 +275,3 @@ describe('isValidOpportunityProduct', () => {
expect(isValidOpportunityProduct()).toEqual(false);
});
});
-describe('snakeCaseWord', () => {
- it('returns snake case word', () => {
- const camelCasedWord = 'helloWorld';
- const snakeCasedWord = 'hello_world';
- expect(snakeCaseWord(camelCasedWord)).toEqual(snakeCasedWord);
- });
-});