Skip to content

Commit

Permalink
O3 4057: Add ability to edit tab definition (#8)
Browse files Browse the repository at this point in the history
* Add ability to edit tab definition

* Add ability to edit tab definition

* fix merge conflicts
  • Loading branch information
lucyjemutai authored Oct 11, 2024
1 parent 2b8f818 commit 2bce1c6
Showing 1 changed file with 213 additions and 122 deletions.
335 changes: 213 additions & 122 deletions src/components/interactive-builder/interactive-builder.component.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useCallback } from 'react';
import { showModal, AddIcon, EditIcon, TrashCanIcon } from '@openmrs/esm-framework';
import React, { useState, useCallback } from 'react';
import { showModal, AddIcon, EditIcon, TrashCanIcon, showSnackbar } from '@openmrs/esm-framework';
import { useTranslation } from 'react-i18next';
import { v4 as uuidv4 } from 'uuid';
import { Button, Accordion, AccordionItem, Tile } from '@carbon/react';
import { Button, Accordion, AccordionItem, Tile, TextInput } from '@carbon/react';
import { DefinitionTypes, WidgetTypes, type DynamicExtensionSlot, type Schema } from '../../types';
import styles from './interactive-builder.scss';
import { getSubMenuSlotDetails } from '../../helpers';
Expand All @@ -14,6 +14,10 @@ interface InteractiveBuilderProps {

const InteractiveBuilder = ({ schema, onSchemaChange }: InteractiveBuilderProps) => {
const { t } = useTranslation();
const [editingTab, setEditingTab] = useState(null);
const [editedTabName, setEditedTabName] = useState('');
const [editedHeaderTitle, setEditedHeaderTitle] = useState('');
const [isEditing, setIsEditing] = useState(false);

const initializeSchema = useCallback(() => {
const dummySchema: Schema = {
Expand Down Expand Up @@ -53,6 +57,56 @@ const InteractiveBuilder = ({ schema, onSchemaChange }: InteractiveBuilderProps)
});
}, [schema, onSchemaChange]);

const handleEditTab = (tabDefinition) => {
setEditingTab(tabDefinition);
setEditedTabName(tabDefinition.tabName);
setEditedHeaderTitle(tabDefinition.headerTitle);
setIsEditing(true);
};

const handleSaveTab = (submenuKey, tabIndex) => {
const updatedSchema = JSON.parse(JSON.stringify(schema));

// Get the dynamic key for the extension slots
const extensionSlots = updatedSchema['@openmrs/esm-patient-chart-app'].extensionSlots;
const extensionSlotKey = Object.keys(extensionSlots)[0]; // Assuming there is only one key, or get it based on your logic

let configureEntry = extensionSlots[extensionSlotKey].configure[submenuKey];

if (!configureEntry) {
configureEntry = { tabDefinitions: [] };
updatedSchema['@openmrs/esm-patient-chart-app'].extensionSlots[extensionSlotKey].configure[submenuKey] =
configureEntry;
}

const updatedTabDefinition = {
...editingTab,
tabName: editedTabName,
headerTitle: editedHeaderTitle,
};

configureEntry.tabDefinitions[tabIndex] = updatedTabDefinition;

onSchemaChange(updatedSchema);

showSnackbar({
title: t('success', 'Success!'),
kind: 'success',
isLowContrast: true,
subtitle: t('tabEditedSuccessfully', 'Tab edited successfully!'),
});

setEditingTab(updatedTabDefinition);
setIsEditing(false);
};

const handleCancelEdit = () => {
setEditingTab(null);
setEditedTabName('');
setEditedHeaderTitle('');
setIsEditing(false);
};

const handleConfigureDashboardModal = useCallback(
(slotName) => {
const dispose = showModal('configure-dashboard-modal', {
Expand Down Expand Up @@ -165,126 +219,163 @@ const InteractiveBuilder = ({ schema, onSchemaChange }: InteractiveBuilderProps)
'Now configure dashboards to show on the patient chart when this submenu is clicked.',
)}
</p>
{subMenuSlotDetails?.configure?.[configurationKey]?.tabDefinitions?.map((tabDefinition, index) => (
<Tile className={styles.tileContainer} key={tabDefinition?.tabName}>
{editingTab === tabDefinition ? (
<>
<TextInput
id="tab-name"
labelText={t('tabName', 'Tab Name')}
value={editedTabName}
onChange={(e) => setEditedTabName(e.target.value)}
/>
<TextInput
id="header-title"
labelText={t('headerTitle', 'Header Title')}
value={editedHeaderTitle}
onChange={(e) => setEditedHeaderTitle(e.target.value)}
/>
<Button onClick={() => handleSaveTab(submenuKey, index)}>{t('save', 'Save')}</Button>
<Button kind="tertiary" onClick={handleCancelEdit}>
{t('cancel', 'Cancel')}
</Button>
</>
) : (
<>
{editingTab && (
<>
<p className={styles.subheading}>{t('tabName', 'Tab name')}</p>
<p>{editingTab.tabName}</p>
<p className={styles.subheading}>{t('headerTitle', 'Header title')}</p>
<p>{editingTab.headerTitle}</p>
</>
)}
<div className={styles.editStatusIcon}>
<Button
size="md"
kind="tertiary"
hasIconOnly
renderIcon={(props) => <EditIcon size={16} {...props} />}
iconDescription={t('editTabDefinition', 'Edit tab definition')}
onClick={() => handleEditTab(tabDefinition)}
/>
<Button
size="md"
kind="tertiary"
hasIconOnly
renderIcon={(props) => <TrashCanIcon size={16} {...props} />}
iconDescription={t('deleteTabDefinition', 'Delete tab definition')}
onClick={() => {
handleDeleteConfigDetailModal(
submenuDetails,
tabDefinition,
configurationKey,
DefinitionTypes.TAB_DEFINITION,
);
}}
/>
</div>
<p className={styles.subheading}>{t('tabName', 'Tab name')}</p>
<p>{tabDefinition?.tabName}</p>
<p className={styles.subheading}>{t('headerTitle', 'Header title')}</p>
<p>{tabDefinition?.headerTitle}</p>
<p className={styles.subheading}>{t('columns', 'Columns')}</p>
{tabDefinition?.columns.map((column) => (
<div className={styles.tileContent} key={column.title}>
<p className={styles.content}>
{t('title', 'Title')} : {column.title ?? '--'}
</p>
<p className={styles.content}>
{t('concept', 'Concept')} : {column.concept ?? '--'}
</p>
<p className={styles.content}>
{column.isDate && (
<>
{t('date', 'Date')} : {column.isDate.toString() ?? '--'}
</>
)}
</p>
<p className={styles.content}>
{column.isLink && (
<>
{t('link', 'Link')} : {column.isLink.toString() ?? '--'}
</>
)}
</p>
</div>
))}
<Button
kind="ghost"
renderIcon={AddIcon}
onClick={() => {
handleConfigureColumnsModal(
submenuDetails,
tabDefinition,
DefinitionTypes.TAB_DEFINITION,
);
}}
>
{t('configureColumns', 'Configure columns')}
</Button>

{subMenuSlotDetails?.configure?.[configurationKey]?.tabDefinitions?.map((tabDefinition) => (
<Tile className={styles.tileContainer}>
<div className={styles.editStatusIcon}>
<Button
size="md"
kind={'tertiary'}
hasIconOnly
renderIcon={(props) => <EditIcon size={16} {...props} />}
iconDescription={t('editTabDefinition', 'Edit tab definition')}
/>
<Button
size="md"
kind={'tertiary'}
hasIconOnly
renderIcon={(props) => <TrashCanIcon size={16} {...props} />}
iconDescription={t('deleteTabDefinition', 'Delete tab definition')}
onClick={() => {
handleDeleteConfigDetailModal(
submenuDetails,
tabDefinition,
configurationKey,
DefinitionTypes.TAB_DEFINITION,
);
}}
/>
</div>
<p className={styles.subheading}>{t('tabName', 'Tab name')}</p>
<p>{tabDefinition?.tabName}</p>
<p className={styles.subheading}>{t('headerTitle', 'Header title')}</p>
<p>{tabDefinition?.headerTitle}</p>
<p className={styles.subheading}>{t('columns', 'Columns')}</p>
{tabDefinition?.columns.map((column) => (
<div className={styles.tileContent}>
<p className={styles.content}>
{t('title', 'Title')} : {column.title ?? '--'}
</p>
<p className={styles.content}>
{t('concept', 'Concept')} : {column.concept ?? '--'}
</p>
<p className={styles.content}>
{column.isDate && (
<>
{t('date', 'Date')} : {column.isDate.toString() ?? '--'}
</>
)}
</p>
<p className={styles.content}>
{column.isLink && (
<>
{t('link', 'Link')} : {column.isLink.toString() ?? '--'}
</>
)}
</p>
</div>
))}
<Button
kind="ghost"
renderIcon={AddIcon}
onClick={() => {
handleConfigureColumnsModal(submenuDetails, tabDefinition, DefinitionTypes.TAB_DEFINITION);
}}
>
{t('configureColumns', 'Configure columns')}
</Button>
</Tile>
))}

{subMenuSlotDetails?.configure[configurationKey]?.tilesDefinitions?.map((tileDefinition) => (
<Tile className={styles.tileContainer}>
<div className={styles.editStatusIcon}>
<Button
size="md"
kind={'tertiary'}
hasIconOnly
renderIcon={(props) => <EditIcon size={16} {...props} />}
iconDescription={t('editTileDefinition', 'Edit tile definition')}
/>
<Button
size="md"
kind={'tertiary'}
hasIconOnly
renderIcon={(props) => <TrashCanIcon size={16} {...props} />}
iconDescription={t('deleteTileDefinition', 'Delete tile definition')}
onClick={() => {
handleDeleteConfigDetailModal(
submenuDetails,
tileDefinition,
configurationKey,
DefinitionTypes.TILE_DEFINITION,
);
}}
/>
</div>
<p className={styles.subheading}>{t('headerTitle', 'Header title')}</p>
<p>{tileDefinition?.tilesHeader}</p>
<p className={styles.subheading}>{t('columns', 'Columns')} </p>
{tileDefinition?.columns.map((column) => (
<div className={styles.tileContent}>
<p className={styles.content}>
{t('title', 'Title')} : {column.title ?? '--'}
</p>
<p className={styles.content}>
{t('concept', 'Concept')} : {column.concept ?? '--'}
</p>
</div>
))}
<Button
kind="ghost"
renderIcon={AddIcon}
onClick={() => {
handleConfigureColumnsModal(
submenuDetails,
tileDefinition,
DefinitionTypes.TILE_DEFINITION,
);
}}
>
{t('configureColumns', 'Configure columns')}
</Button>
{subMenuSlotDetails?.configure[configurationKey]?.tilesDefinitions?.map(
(tileDefinition) => (
<Tile className={styles.tileContainer} key={tileDefinition?.tilesHeader}>
<div className={styles.editStatusIcon}>
<Button
size="md"
kind="tertiary"
hasIconOnly
renderIcon={(props) => <EditIcon size={16} {...props} />}
iconDescription={t('editTileDefinition', 'Edit tile definition')}
/>
<Button
size="md"
kind="tertiary"
hasIconOnly
renderIcon={(props) => <TrashCanIcon size={16} {...props} />}
iconDescription={t('deleteTileDefinition', 'Delete tile definition')}
onClick={() => {
handleDeleteConfigDetailModal(
submenuDetails,
tileDefinition,
configurationKey,
DefinitionTypes.TILE_DEFINITION,
);
}}
/>
</div>
<p className={styles.subheading}>{t('headerTitle', 'Header title')}</p>
<p>{tileDefinition?.tilesHeader}</p>
<p className={styles.subheading}>{t('columns', 'Columns')}</p>
{tileDefinition?.columns.map((column) => (
<div className={styles.tileContent} key={column.title}>
<p className={styles.content}>
{t('title', 'Title')} : {column.title ?? '--'}
</p>
<p className={styles.content}>
{t('concept', 'Concept')} : {column.concept ?? '--'}
</p>
</div>
))}
<Button
kind="ghost"
renderIcon={AddIcon}
onClick={() => {
handleConfigureColumnsModal(
submenuDetails,
tileDefinition,
DefinitionTypes.TILE_DEFINITION,
);
}}
>
{t('configureColumns', 'Configure columns')}
</Button>
</Tile>
),
)}
</>
)}
</Tile>
))}
<Button
Expand Down

0 comments on commit 2bce1c6

Please sign in to comment.