Skip to content

Commit

Permalink
Re-designed the flow and auto-updating the existing books & chapters …
Browse files Browse the repository at this point in the history
…in the scope from the backend
  • Loading branch information
vipinpaul committed Aug 28, 2024
1 parent e455b43 commit d8564ea
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 77 deletions.
124 changes: 70 additions & 54 deletions renderer/src/components/ProjectManagement/ProjectManagement.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ import React, {
useRef, Fragment,
useEffect,
useCallback,
useState,
} from 'react';
import PropTypes from 'prop-types';
import { Dialog, Transition } from '@headlessui/react';
import { useTranslation } from 'react-i18next';
import updateTranslationSB from '@/core/burrito/updateTranslationSB';
import updateObsSB from '@/core/burrito/updateObsSB';
import { SnackBar } from '@/components/SnackBar';
// import useSystemNotification from '@/components/hooks/useSystemNotification';
// import { LoadingSpinner } from '@/components/LoadingSpinner';
import ConfirmationModal from '@/layouts/editor/ConfirmationModal';
// import ConfirmationModal from '@/layouts/editor/ConfirmationModal';
import CloseIcon from '@/illustrations/close-button-black.svg';
import * as logger from '../../logger';
import burrito from '../../lib/BurritoTemplate.json';
import ScopeManagement from './scope-management/ScopeManagement';
import { readProjectScope } from './utils/readProjectScope';
import { LoadingSpinner } from '../LoadingSpinner';
import { updateBurritoScope } from './utils/updateBurritoScope';

export default function ProjectMangement(props) {
const {
Expand All @@ -28,50 +27,19 @@ export default function ProjectMangement(props) {
} = props;
const { t } = useTranslation();
const cancelButtonRef = useRef(null);
const [valid, setValid] = React.useState(false);
const [snackBar, setOpenSnackBar] = React.useState(false);
const [snackText, setSnackText] = React.useState('');
const [notify, setNotify] = React.useState();
const [openModal, setOpenModal] = React.useState(false);
const [checkText, setCheckText] = React.useState(false);
const [totalExported, setTotalExported] = React.useState(0);
const [totalExports, setTotalExports] = React.useState(0);
const [exportStart, setExportstart] = React.useState(false);
const [snackBar, setOpenSnackBar] = useState(false);
const [snackText, setSnackText] = useState('');
const [notify, setNotify] = useState();
const [currentScope, setCurrentScope] = useState({});
const [metadata, setMetadata] = useState('');
const [loading, setLoading] = useState(false);
const [backendScope, setBackendScope] = useState({});

const [metadata, setMetadata] = React.useState('');
const [loading, setLoading] = React.useState(false);

// const { pushNotification } = useSystemNotification();

function resetExportProgress() {
logger.debug('ExportProjectPopUp.js', 'reset Export Progress');
if (!exportStart) {
setTotalExported(0);
setTotalExports(0);
setExportstart(false);
}
}

function close() {
if (!exportStart) {
logger.debug('ExportProjectPopUp.js', 'Closing the Dialog Box');
resetExportProgress(); // reset export
closePopUp(false);
setValid(false);
setMetadata({});
setCheckText(false);
}
}

const updateBurritoVersion = (username) => {
logger.debug('ExportProjectPopUp.js', 'Inside updateBurritoVersion');
setTotalExported(1); // 1 step of 2 finished
if (project?.type === 'Text Translation') {
updateTranslationSB(username, project, openModal);
} else if (project?.type === 'OBS') {
updateObsSB(username, project, openModal);
}
setOpenModal(false);
const close = () => {
logger.debug('ProjectMangement.js', 'Closing the Dialog Box');
setOpenSnackBar(true);
closePopUp(false);
setMetadata({});
};

// load Metadata of the project
Expand All @@ -80,13 +48,61 @@ export default function ProjectMangement(props) {
setLoading(true);
const projectFullName = `${project?.name}_${project?.id?.[0]}`;
const projectMeta = await readProjectScope(projectFullName);
setMetadata(projectMeta);
setMetadata(projectMeta.metadata);
setBackendScope(projectMeta.scope);
} catch (err) {
console.error('Read Meta : ', err);

Check warning on line 54 in renderer/src/components/ProjectManagement/ProjectManagement.js

View workflow job for this annotation

GitHub Actions / Lint Run

Unexpected console statement

Check warning on line 54 in renderer/src/components/ProjectManagement/ProjectManagement.js

View workflow job for this annotation

GitHub Actions / Lint Run

Unexpected console statement
} finally {
setLoading(false);
}
}, [project]);
function compareNumbers(a, b) {
return a - b;
}
const handleProject = () => {
logger.debug('ProjectMangement.js', 'Inside updateBurrito');
let mergedScope = currentScope;
// Merge both existing and new scope, if any scope difference exists
if (Object.keys(backendScope).length > 0) {
Object.entries(backendScope).forEach((book) => {
// Checking whether the book in scope is available in currentscope
if (currentScope[book[0]]) {
// merging the chapters of existing and selected books
const scopeSet = backendScope[book[0]];
const currentSet = currentScope[book[0]];
const arr = [...scopeSet, ...currentSet];
const mergedArr = [...new Set(arr)];
mergedScope = { ...mergedScope, [book[0]]: mergedArr.sort(compareNumbers) };
} else {
mergedScope = { ...mergedScope, [book[0]]: Object.values(backendScope[book[0]]) };
}
});
}
metadata.type.flavorType.currentScope = mergedScope;
const projectFullName = `${project?.name}_${project?.id?.[0]}`;
updateBurritoScope(projectFullName, metadata).then(() => {
setNotify('success');
setSnackText('Scope updated successfully!');
close();
});
};

// const handleProject = () => {
// metadata.type.flavorType.currentScope = currentScope;
// const projectFullName = `${project?.name}_${project?.id?.[0]}`;
// // updateBurritoScope checks whether user has removed anything (Book(s)/Chapter(s)) from the existing scope or not
// updateBurritoScope(projectFullName, metadata, 'difference').then((value) => {
// console.log('scope', value);
// if (Object.keys(value).length > 0) {
// // Has some change so merge is required
// setScopeDiff(value);
// // setOpenModal(true);
// } else {
// // nothing been removed by the user
// updateBurrito();
// }
// });
// };

useEffect(() => {
getProjectMetadata();
Expand Down Expand Up @@ -138,7 +154,7 @@ export default function ProjectMangement(props) {
<div className=" w-full h-full flex-1 flex flex-col overflow-y-scroll mb-5">

<div className="flex-grow-[5]">
{loading ? <LoadingSpinner /> : <ScopeManagement metadata={metadata} />}
{loading ? <LoadingSpinner /> : <ScopeManagement metadata={metadata} currentScope={currentScope} setCurrentScope={setCurrentScope} backendScope={backendScope} />}
</div>

<div className="h-[10%] flex justify-end items-center me-5">
Expand All @@ -154,7 +170,7 @@ export default function ProjectMangement(props) {
type="button"
aria-label="edit-language"
className=" bg-success w-28 h-8 border-color-success rounded uppercase text-white text-xs shadow focus:outline-none"
onClick={() => console.log('Apply scope change clicked')}
onClick={() => handleProject()}
>
Apply
</button>
Expand All @@ -174,16 +190,16 @@ export default function ProjectMangement(props) {
setSnackText={setSnackText}
error={notify}
/>
<ConfirmationModal
{/* <ConfirmationModal
openModal={openModal}
title={t('modal-title-update-burrito')}
setOpenModal={setOpenModal}
confirmMessage={t('dynamic-msg-update-burrito-version', { version1: metadata?.metadata?.meta?.version, version2: burrito?.meta?.version })}
confirmMessage={t('dynamic-msg-scope-difference', { scopediff: JSON.stringify(scopediff) })}
buttonName={t('btn-update')}
closeModal={
() => updateBurritoVersion(metadata.username, metadata.fs, metadata.path, metadata.folder)
() => updateBurrito()
}
/>
/> */}
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
/* eslint-disable no-nested-ternary */
import React from 'react';
import BookButton from '../Common/Button/BookButton';
import XMark from '@/icons/Xelah/XMark.svg';

function BookItem({
book, handleSelectBook, handleRemoveScope, isInScope,
book, handleSelectBook, handleRemoveScope, isInScope, disable,
}) {
return (
<div className="flex items-center">
<BookButton
className={`flex items-center gap-1.5 w-full border ${isInScope ? 'bg-primary/25' : ''}`}
className={`flex items-center gap-1.5 w-full border ${disable ? 'bg-gray-400' : (isInScope ? 'bg-primary/25' : '')}`}
onClick={(e) => handleSelectBook(e, book)}
>
<div
title={isInScope ? 'Modify Chapters' : 'Add to scope'}
title={disable ? 'Auto-Selected' : isInScope ? 'Modify Chapters' : 'Add to scope'}
role="button"
tabIndex={-2}
className="flex-[3.5] truncate text-left"
Expand All @@ -22,7 +23,7 @@ function BookItem({

<XMark
title="Remove Scope"
className={`flex-1 w-2 h-5 text-black hover:text-white ${isInScope ? 'visible' : 'opacity-0 pointer-events-none'}`}
className={`flex-1 w-2 h-5 text-black hover:text-white ${disable ? 'opacity-0 pointer-events-none' : (isInScope ? 'visible' : 'opacity-0 pointer-events-none')}`}
onClick={(e) => handleRemoveScope(e, book)}
/>
</BookButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ const ToggleChapterOptions = [
{ key: 'none', name: 'Deselect' },
];

function ScopeManagement({ metadata }) {
function ScopeManagement({
metadata, currentScope, setCurrentScope, backendScope,
}) {
const [bookFilter, setBookFilter] = useState('');
const [chapterFilter, setChapterFilter] = useState('');
const [currentScope, setCurrentScope] = useState({});
const [selectedChaptersSet, setSelectedChaptersSet] = useState(new Set([]));

const {
Expand All @@ -51,7 +52,7 @@ function ScopeManagement({ metadata }) {
});

console.log('BOOK ============>', {
bookName, bookId, metadata, currentScope,
bookName, bookId, metadata, currentScope, backendScope,
});

const handleChangeBookToggle = (event) => {
Expand Down Expand Up @@ -191,7 +192,7 @@ function ScopeManagement({ metadata }) {
<div className="border border-[#eeecec] shadow-sm rounded-lg bg-[#F9F9F9]
grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-1 p-4 text-xxs text-left uppercase"
>
{bookList?.slice(0, 39)?.map((book) => {
{backendScope && bookList?.slice(0, 39)?.map((book) => {
const isScope = book?.key?.toUpperCase() in currentScope;
return (
<BookItem
Expand All @@ -200,6 +201,7 @@ function ScopeManagement({ metadata }) {
handleRemoveScope={handleRemoveScope}
handleSelectBook={handleSelectBook}
isInScope={isScope}
disable={book?.key?.toUpperCase() in backendScope}
/>
);
})}
Expand All @@ -208,7 +210,7 @@ function ScopeManagement({ metadata }) {
<div className="border border-[#eeecec] shadow-sm rounded-lg bg-[#F9F9F9]
grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-1 p-4 text-xxs text-left uppercase content-start"
>
{bookList?.slice(39)?.map((book) => {
{backendScope && bookList?.slice(39)?.map((book) => {
const isScope = book?.key?.toUpperCase() in currentScope;
return (
<BookItem
Expand All @@ -217,23 +219,26 @@ function ScopeManagement({ metadata }) {
handleRemoveScope={handleRemoveScope}
handleSelectBook={handleSelectBook}
isInScope={isScope}
disable={book?.key?.toUpperCase() in backendScope}
/>
);
})}
</div>
</div>

<TitleBar>
<p className="text-gray-900 text-center text-sm flex gap-2">
<span>Chapter Selection :</span>
<span className="font-medium">{bookName}</span>
</p>
<BulkSelectionGroup
selectedOption={chapterFilter}
handleSelect={handleChangeChapterToggle}
toggleOptions={ToggleChapterOptions}
/>
</TitleBar>
{bookName
&& (
<TitleBar>
<p className="text-gray-900 text-center text-sm flex gap-2">
<span>Chapter Selection :</span>
<span className="font-medium">{bookName}</span>
</p>
<BulkSelectionGroup
selectedOption={chapterFilter}
handleSelect={handleChangeChapterToggle}
toggleOptions={ToggleChapterOptions}
/>
</TitleBar>
)}

<form className="w-full my-2 flex gap-3 h-6 text-xxs justify-end" onSubmit={handleChapterRangeSelection}>
<div className="flex gap-1 items-center ">
Expand Down Expand Up @@ -268,11 +273,13 @@ function ScopeManagement({ metadata }) {
<div className="border border-[#eeecec] shadow-sm rounded-lg bg-[#F9F9F9] flex flex-wrap gap-2 p-4 text-xxs text-left uppercase">
{chapterList?.map(({ key, name }) => {
const isInScope = selectedChaptersSet.has(key);
const disable = backendScope[bookId.toUpperCase()]?.includes(key);
return (
<BookButton
onClick={(e) => handleChapterSelection(e, name)}
key={key}
className={`border min-w-8 text-center ${isInScope ? 'bg-primary text-white font-medium' : ''}`}
// eslint-disable-next-line no-nested-ternary
className={`border min-w-8 text-center ${disable ? 'bg-gray-400' : isInScope ? 'bg-primary text-white font-medium' : ''}`}
>
{name}
</BookButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@ import localForage from 'localforage';
import * as logger from '../../../logger';
import packageInfo from '../../../../../package.json';

const getDirectories = (readdirSync, source) => readdirSync(source, { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);

// This function returns the Object of books & chapters which has atleast 1 audio file in it.
export const getScope = (project) => {
const path = require('path');
const scope = {};
const { readdirSync } = window.require('fs');
const list = getDirectories(readdirSync, project);
list.forEach((book) => {
const chapters = getDirectories(readdirSync, path.join(project, book));
scope[book] = chapters;
});
return scope;
};
export const readProjectScope = async (projectName) => {
try {
logger.debug('readProjectScope.js', `In read metadata - ${projectName}`);
Expand All @@ -17,8 +33,10 @@ export const readProjectScope = async (projectName) => {
const metadataFile = await fs.readFileSync(filePath, 'utf-8');
if (metadataFile) {
logger.debug('metadataFile.js', `read metadata file successfully - ${projectName}`);
const project = path.join(file, projectName, 'audio', 'ingredients');
const backendScope = getScope(project);
const json = await JSON.parse(metadataFile);
return json;
return { metadata: json, scope: backendScope };
}
throw new Error(`failed to read settings file - ${projectName}`);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import localForage from 'localforage';
import * as logger from '../../../logger';
import packageInfo from '../../../../../package.json';

export const updateBurritoScope = async (projectName, metadata) => {
try {
logger.debug('updateBurritoScope.js', `In update metadata - ${projectName}`);
const currentUser = await localForage.getItem('userProfile');
const newpath = localStorage.getItem('userPath');
const fs = window.require('fs');
const path = require('path');
const file = path.join(newpath, packageInfo.name, 'users', currentUser.username, 'projects');
// Finally updating the scope in the metadata
const filePath = path.join(file, projectName, 'metadata.json');
if (fs.existsSync(filePath)) {
fs.writeFileSync(filePath, JSON.stringify(metadata));
return true;
}
throw new Error(`failed to read metadata file - ${projectName}`);
} catch (err) {
logger.error('updateBurritoScope.js', `read metadata file successfully - ${projectName}`);
throw new Error(err?.message || err);
}
};

0 comments on commit d8564ea

Please sign in to comment.