Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions backend/models/core/Entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,108 @@ class Entity {
//TODO: end transaction
return true;
}

// POST multiple entries to database
static async batchUpload(entry) {
const db = new DB();

const selectedProperties = ['slug', 'entity_type_id'];

const entitiesBatchParams = entry.map((obj) => {
return selectedProperties.map((name) => {
const value = obj[name];
const transformedValue =
typeof value === 'number' ? { longValue: value } : { stringValue: value };
return {
name,
value: transformedValue
};
});
});

const insertEntitiesSQL = `INSERT into entities (slug, entity_type_id)
VALUES (:slug, :entity_type_id)`;

await db.batchExecuteStatement(insertEntitiesSQL, entitiesBatchParams);

const {
records: [[{ longValue: lastInsertedEntityID }]],
} = await db.executeStatement("SELECT LAST_INSERT_ID()");

//Attribute Introspection
const entityIntrospectionSQL = `SELECT id, name, type
FROM attributes
WHERE entity_type_id = :entity_type_id ORDER by \`order\``;

const attributes = await db.executeStatement(entityIntrospectionSQL, [
{ name: "entity_type_id", value: { longValue: entry[0].entity_type_id } },
]);

let valueBatchParams = [];

entry.map((x, i) => {
const params = attributes.records.reduce((collection, record) => {
const [
{ longValue: attributeId },
{ stringValue: attributeName },
{ stringValue: attributeType },
] = record;

return [
...collection,
[
{ name: "entity_id", value: { longValue: (lastInsertedEntityID + i) } },
{ name: "attribute_id", value: { longValue: attributeId } },
//Refactor to encapsulate type switch
{
name: "value_string",
value:
attributeType == "text" ||
attributeType == "image" ||
attributeType == "link" ||
attributeType === "video"
? { stringValue: x[attributeName] }
: { isNull: true },
},
{
name: "value_long_string",
value:
attributeType == "textarea" ||
attributeType === "gallery" ||
attributeType === "rich-text" ||
attributeType == "custom"
? { stringValue: x[attributeName] }
: { isNull: true },
},
{
name: "value_double",
value:
attributeType == "float" && x[attributeName].trim() != ''
? { doubleValue: x[attributeName] }
: { isNull: true },
},
{
name: "value_boolean",
value:
attributeType == "boolean"
? { booleanValue: x[attributeName] }
: { isNull: true },
},
],
];
}, []);

valueBatchParams = valueBatchParams.concat(params);
});

const insertValuesBatchSQL = `INSERT INTO \`values\`(entity_id, attribute_id,
value_string, value_long_string, value_double, value_boolean)
VALUES (:entity_id, :attribute_id, :value_string, :value_long_string, :value_double, :value_boolean)`;

await db.batchExecuteStatement(insertValuesBatchSQL, valueBatchParams);

return true;
}
}

export default Entity;
11 changes: 11 additions & 0 deletions components/loading/LoadingScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const LoadingScreen = () => (
<div className="loading-screen">
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
<div className="dot"></div>
</div>
);

export default LoadingScreen;
38 changes: 38 additions & 0 deletions components/modals/ErrorModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Modal from 'react-bootstrap/Modal';
import { Poppins } from '@next/font/google';
import { FaTimes } from 'react-icons/fa';
import { IoIosCloseCircleOutline } from 'react-icons/io';
import cx from "classnames";

const poppins = Poppins({
weight: ['300', '400', '500', '600', '700'],
subsets: ['latin'],
display: 'swap',
})

const ErrorModal = ({ show, message, hide }) => {
return (
<Modal
show={show}
centered
size='md'
onHide={hide}
>
<Modal.Body className={cx(poppins.className, "general-modal-error-body")}>
<div className="general-modal-error">
<div className="general-modal-error-icon-container">
<div className="general-modal-error-header">
<div className="general-modal-error-header-icon" onClick={hide}>
<FaTimes />
</div>
</div>
<IoIosCloseCircleOutline className="general-modal-error-icon" />
</div>
<div className="general-modal-error-title"> Ooops! </div>
{message}
</div>
</Modal.Body>
</Modal>
)
}
export default ErrorModal;
41 changes: 41 additions & 0 deletions components/modals/LoadingModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Modal from 'react-bootstrap/Modal';
import LoadingScreen from '../loading/LoadingScreen';
import { Poppins } from '@next/font/google';
import { FaTimes } from 'react-icons/fa';
import { IoIosCheckmarkCircleOutline } from 'react-icons/io';
import cx from "classnames";

const poppins = Poppins({
weight: ['300', '400', '500', '600', '700'],
subsets: ['latin'],
display: 'swap',
})

const LoadingModal = ({ show, loading, message, hide }) => {
return (
<Modal
show={show}
centered
size='md'
onHide={!loading ? () => hide() : null}
>
<Modal.Body className={cx(poppins.className, "general-modal-loading-body-default", {"general-modal-loading-body" : !loading} )}>
{loading && <LoadingScreen />}
{!loading &&
<div className="general-modal-loading">
<div className="general-modal-loading-icon-container">
<div className="general-modal-loading-header">
<div className="general-modal-loading-header-icon" onClick={hide}>
<FaTimes />
</div>
</div>
<IoIosCheckmarkCircleOutline className="general-modal-loading-icon" />
</div>
<div className="general-modal-loading-title"> Great! </div>
{message}
</div>}
</Modal.Body>
</Modal>
)
}
export default LoadingModal;
13 changes: 11 additions & 2 deletions components/reducers/contentManagerReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
SET_MODAL_CONTENT,
SET_DATA,
SET_METADATA,
SET_IMPORT_CSV_MODAL
} from "@/lib/actions";

export const initialState = {
Expand All @@ -36,10 +37,13 @@ export const initialState = {
modalContent: null,
view: 'list',
data: {},
metadata: {}
metadata: {},
importCSVModal: {
show: false,
loading: false,
}
};


export const contentManagerReducer = (state, action) => {
switch (action.type) {
case LOADING:
Expand Down Expand Up @@ -141,5 +145,10 @@ export const contentManagerReducer = (state, action) => {
...state,
metadata: action.payload
}
case SET_IMPORT_CSV_MODAL:
return {
...state,
importCSVModal: action.payload
};
}
};
10 changes: 10 additions & 0 deletions db/migrations/202307040350120_insert_download_csv_capability.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"up": [
"REPLACE INTO capabilities (name, description, is_system_supplied) VALUES",
"('import_csv', 'Can import CSV file', true)"
],
"down":[
"DELETE FROM capabilities WHERE name = 'import_csv'"
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"up": [
"REPLACE INTO group_capabilities (group_id, capabilities_id) VALUES",
"(1, (SELECT id FROM capabilities WHERE name = 'import_csv' AND is_system_supplied = true))"
],
"down":[
"DELETE FROM group_capabilities WHERE group_id IN = 1",
"AND capabilities_id = (SELECT id FROM capabilities WHERE name = 'import_csv' AND is_system_supplied = true);"
]
}

1 change: 1 addition & 0 deletions lib/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const rejectUsers = 'reject_users';
export const changeUserPassword = 'change_user_password';
export const deleteUsers = 'delete_users';
export const downloadCSV = 'download_csv';
export const importCSV = 'import_csv';


// password creation
Expand Down
1 change: 1 addition & 0 deletions lib/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ export const SET_CURRENT_ICON = 'SET_CURRENT_ICON';
export const SET_GROUPS = 'SET_GROUPS';
export const SET_DATA = 'SET_DATA';
export const SET_METADATA = 'SET_METADATA';
export const SET_IMPORT_CSV_MODAL = 'SET_IMPORT_CSV_MODAL';
Loading