Skip to content

Commit

Permalink
feat: move analytics tab to analytics view (#141)
Browse files Browse the repository at this point in the history
* feat: move analytics tab to analytics view

* fix: remove navigate to analytics tab at builder view
  • Loading branch information
LinaYahya authored Mar 7, 2024
1 parent fa3c57a commit a21e06b
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 96 deletions.
13 changes: 0 additions & 13 deletions cypress/e2e/Admin/AdminView.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { getSettingsByName } from '../../../src/components/context/utilities';
import { APP_SETTING_NAMES } from '../../../src/config/constants';
import {
ADD_NEW_QUESTION_TITLE_CY,
ANALYTICS_CONTAINER_CY,
CREATE_VIEW_CONTAINER_CY,
NAVIGATION_ANALYTICS_BUTTON_CY,
NAVIGATION_CREATE_QUIZ_BUTTON_CY,
NAVIGATION_RESULT_BUTTON_CY,
NAVIGATION_TAB_CONTAINER_CY,
Expand Down Expand Up @@ -39,12 +37,6 @@ describe('Admin View', () => {
'have.text',
"There isn't any question to display"
);

cy.get(dataCyWrapper(NAVIGATION_ANALYTICS_BUTTON_CY)).click();
cy.get(dataCyWrapper(ANALYTICS_CONTAINER_CY)).should(
'have.text',
"There isn't any question to display"
);
});

/**
Expand Down Expand Up @@ -86,14 +78,9 @@ export const testAdminViewBaseLayout = () => {
cy.get(dataCyWrapper(NAVIGATION_TAB_CONTAINER_CY)).should('be.visible');
cy.get(dataCyWrapper(NAVIGATION_CREATE_QUIZ_BUTTON_CY)).should('be.visible');
cy.get(dataCyWrapper(NAVIGATION_RESULT_BUTTON_CY)).should('be.visible');
cy.get(dataCyWrapper(NAVIGATION_ANALYTICS_BUTTON_CY)).should('be.visible');
cy.get(dataCyWrapper(NAVIGATION_RESULT_BUTTON_CY)).click();

// after we click on result, the table component should be visible and the table
cy.get(dataCyWrapper(CREATE_VIEW_CONTAINER_CY)).should('not.exist');
cy.get(dataCyWrapper(TABLE_BY_QUESTION_CONTAINER_CY)).should('be.visible');

// after clicking on analytics, the component should be visible
cy.get(dataCyWrapper(NAVIGATION_ANALYTICS_BUTTON_CY)).click();
cy.get(dataCyWrapper(ANALYTICS_CONTAINER_CY)).should('be.visible');
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { getSettingsByName } from '../../../../src/components/context/utilities';
import { getSettingsByName } from '../../../src/components/context/utilities';
import {
APP_SETTING_NAMES,
QuestionType,
} from '../../../../src/config/constants';
} from '../../../src/config/constants';
import {
buildAnalyticsDetailedChartCy,
buildAnalyticsDetailedQuestionTabMenuCy,
dataCyWrapper,
} from '../../../../src/config/selectors';
import { ANSWER_REGEXP } from '../../../../src/utils/fillInTheBlanks';
import { APP_DATA_LOT_QUESTIONS_LOT_USERS } from '../../../fixtures/appData';
import { APP_SETTINGS_LOT_QUESTIONS } from '../../../fixtures/appSettings';
import { MEMBERS_RESULT_TABLES } from '../../../fixtures/members';
import { verifySelectedMenu } from '../../../utils/autoScrollableMenuSelected';
} from '../../../src/config/selectors';
import { ANSWER_REGEXP } from '../../../src/utils/fillInTheBlanks';
import { APP_DATA_LOT_QUESTIONS_LOT_USERS } from '../../fixtures/appData';
import { APP_SETTINGS_LOT_QUESTIONS } from '../../fixtures/appSettings';
import { MEMBERS_RESULT_TABLES } from '../../fixtures/members';
import { verifySelectedMenu } from '../../utils/autoScrollableMenuSelected';

describe('Analytics Detailed', () => {

it('Selecting detailed chart display correct answer frequency chart based on question type', () => {
cy.setupAnalyticsForCheck(
APP_SETTINGS_LOT_QUESTIONS,
Expand All @@ -38,13 +39,13 @@ describe('Analytics Detailed', () => {
case QuestionType.FILL_BLANKS:
q.data.text
.match(ANSWER_REGEXP)
.map((word, idx) => {
.map((word, idx) =>
// todo: use id instead of label
return {
({
label: `Question answer frequency blank ${idx + 1}`,
id: `Question answer frequency blank ${idx + 1}`,
};
})
})
)
.forEach((qLabel, idx, labels) => {
// Goes to chart
cy.get(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getSettingsByName } from '../../../../src/components/context/utilities';
import { APP_SETTING_NAMES } from '../../../../src/config/constants';
import { getSettingsByName } from '../../../src/components/context/utilities';
import { APP_SETTING_NAMES } from '../../../src/config/constants';
import {
ANALYTICS_CONTAINER_CY,
ANALYTICS_GENERAL_CORRECT_RESPONSE_PERCENTAGE_CY,
Expand All @@ -9,14 +9,14 @@ import {
buildAnalyticsDetailedQuestionTabMenuCy,
buildAutoScrollableMenuLinkCy,
dataCyWrapper,
} from '../../../../src/config/selectors';
import { APP_DATA_LOT_QUESTIONS_LOT_USERS } from '../../../fixtures/appData';
} from '../../../src/config/selectors';
import { APP_DATA_LOT_QUESTIONS_LOT_USERS } from '../../fixtures/appData';
import {
APP_SETTINGS_FEW_QUESTIONS,
APP_SETTINGS_LOT_QUESTIONS,
} from '../../../fixtures/appSettings';
import { MEMBERS_RESULT_TABLES } from '../../../fixtures/members';
import { verifySelectedMenu } from '../../../utils/autoScrollableMenuSelected';
} from '../../fixtures/appSettings';
import { MEMBERS_RESULT_TABLES } from '../../fixtures/members';
import { verifySelectedMenu } from '../../utils/autoScrollableMenuSelected';

const generalCharts = [
{
Expand Down Expand Up @@ -103,30 +103,6 @@ describe('Analytics General', () => {
});
});

// bug: transition fails in cypress
// it('Analytics, click chart in menu goes to correct charts', () => {
// cy.setupAnalyticsForCheck(
// APP_SETTINGS_LOT_QUESTIONS,
// APP_DATA_LOT_QUESTIONS_LOT_USERS,
// MEMBERS_RESULT_TABLES
// );

// generalCharts.forEach(({ selector, chartTitle, label, id }, index) => {
// cy.get(dataCyWrapper(buildAutoScrollableMenuLinkCy(id)))
// .scrollIntoView()
// .click();
// // check that correct menu is selected
// verifySelectedMenu(index, generalCharts);

// cy.get(dataCyWrapper(selector)).should('be.visible');

// // Check the title of the chart as well
// cy.get(dataCyWrapper(selector))
// .find('.gtitle')
// .should('have.text', chartTitle);
// });
// });

it('Scroll to chart, select correct menu entry', () => {
cy.setupAnalyticsForCheck(
APP_SETTINGS_LOT_QUESTIONS,
Expand Down
6 changes: 1 addition & 5 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
EXPLANATION_PLAY_CY,
HINTS_CY,
HINTS_PLAY_CY,
NAVIGATION_ANALYTICS_BUTTON_CY,
NAVIGATION_RESULT_BUTTON_CY,
NUMBER_OF_ATTEMPTS_TEXT_CY,
RESULT_TABLES_RESULT_BY_USER_BUTTON_CY,
Expand Down Expand Up @@ -151,15 +150,12 @@ Cypress.Commands.add(
},
appContext: {
permission: PermissionLevel.Admin,
context: Context.Builder,
context: Context.Analytics,
},
members,
});

cy.visit('/');

// navigate to Analytics
cy.get(dataCyWrapper(NAVIGATION_ANALYTICS_BUTTON_CY)).click();
}
);

Expand Down
36 changes: 11 additions & 25 deletions src/components/Analytics/AnalyticsMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import groupBy from 'lodash.groupby';

import {
RefObject,
SyntheticEvent,
useCallback,
useContext,
Expand Down Expand Up @@ -46,19 +45,7 @@ import GeneralCharts from './generalCharts/GeneralCharts';

const SLIDE_BAR_WIDTH = 16;

type Props = {
headerElem: RefObject<HTMLElement | undefined>;
};

export type ChartRefs = RefObject<{ [key: string]: unknown }>;

/**
* Component that represents the Analytics menu. Handle which charts have to be drawn.
*
* @param headerElem The header element if any, used to calculate the remaining height that this object can take
* in the window
*/
const AnalyticsMenu = ({ headerElem }: Props): JSX.Element => {
const AnalyticsMenu = (): JSX.Element => {
const { t } = useTranslation();

// Fetch all the data here, as it is used by multiple children, avoid to fetch it in all children
Expand All @@ -73,12 +60,11 @@ const AnalyticsMenu = ({ headerElem }: Props): JSX.Element => {
useState(true);
const chartRefs = useRef({});
const chartContainerRef = useRef(null);
const [stackElem, setStackElem] = useState<HTMLElement | null>(null);
const [sideMenuElem, setSideMenuElem] = useState<HTMLElement | null>(null);
const stackElem = useRef(null);
const sideMenuElem = useRef(null);

const chartTabs = useRef(null);
const maxResultViewHeight = useMaxAvailableHeightInWindow(
headerElem?.current
);
const maxResultViewHeight = useMaxAvailableHeightInWindow(null);
const maxHeightScrollableMenu = useMaxAvailableHeightWithParentHeight(
maxResultViewHeight,
chartTabs.current
Expand All @@ -90,8 +76,8 @@ const AnalyticsMenu = ({ headerElem }: Props): JSX.Element => {
[questions]
);

const stackElemWidth = useElementWidth(stackElem);
const sideMenuElemWidth = useElementWidth(sideMenuElem);
const stackElemWidth = useElementWidth(stackElem.current);
const sideMenuElemWidth = useElementWidth(sideMenuElem.current);

// TODO: check if it is possible to delete old answers app data
// For now, when a question is removed, the user answers still exists.
Expand Down Expand Up @@ -200,10 +186,10 @@ const AnalyticsMenu = ({ headerElem }: Props): JSX.Element => {

return order.length > 0 ? (
responses && nValidResponses && nValidResponses > 0 ? (
<Box data-cy={ANALYTICS_CONTAINER_CY}>
<Stack direction="row" ref={(elem) => setStackElem(elem)}>
<Box data-cy={ANALYTICS_CONTAINER_CY} sx={{ height: '100%' }}>
<Stack direction="row" ref={stackElem} sx={{ height: '100%' }}>
<Box
ref={(elem: HTMLElement) => setSideMenuElem(elem)}
ref={sideMenuElem}
sx={{
minWidth: '8em',
maxWidth: '12em',
Expand Down Expand Up @@ -249,7 +235,7 @@ const AnalyticsMenu = ({ headerElem }: Props): JSX.Element => {
})}
</Tabs>
</Box>
<Box sx={{ maxHeight: maxHeightScrollableMenu, overflow: 'auto' }}>
<Box sx={{ overflow: 'auto', maxHeight: maxHeightScrollableMenu }}>
<AutoScrollableMenu
links={charts}
elemRefs={chartRefs}
Expand Down
11 changes: 11 additions & 0 deletions src/components/Analytics/AnalyticsView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Box } from '@mui/material';

import AnalyticsMenu from './AnalyticsMenu';

const AnalyticsView = (): JSX.Element => (
<Box sx={{ width: '100%' }}>
<AnalyticsMenu />
</Box>
);

export default AnalyticsView;
9 changes: 0 additions & 9 deletions src/components/navigation/AdminView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import { Tab, Tabs } from '@mui/material';
import Box from '@mui/material/Box';

import {
NAVIGATION_ANALYTICS_BUTTON_CY,
NAVIGATION_CREATE_QUIZ_BUTTON_CY,
NAVIGATION_RESULT_BUTTON_CY,
NAVIGATION_TAB_CONTAINER_CY,
} from '../../config/selectors';
import AnalyticsMenu from '../Analytics/AnalyticsMenu';
import CreateView from '../create/CreateView';
import ResultTables from '../results/ResultTables';
import TabPanel from './TabPanel';
Expand All @@ -37,10 +35,6 @@ const AdminView = () => {
data-cy={NAVIGATION_CREATE_QUIZ_BUTTON_CY}
/>
<Tab label={t('Results')} data-cy={NAVIGATION_RESULT_BUTTON_CY} />
<Tab
label={t('Analytics')}
data-cy={NAVIGATION_ANALYTICS_BUTTON_CY}
/>
</Tabs>
</Box>
<TabPanel tab={tab} index={0}>
Expand All @@ -49,9 +43,6 @@ const AdminView = () => {
<TabPanel tab={tab} index={1}>
<ResultTables headerElem={headerElem} />
</TabPanel>
<TabPanel tab={tab} index={2}>
<AnalyticsMenu headerElem={headerElem} />
</TabPanel>
</Box>
);
};
Expand Down
3 changes: 3 additions & 0 deletions src/components/views/View.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Context, PermissionLevel } from '@graasp/sdk';

import { DEFAULT_LANG } from '../../config/constants';
import i18n from '../../config/i18n';
import AnalyticsView from '../Analytics/AnalyticsView';
import { QuizProvider } from '../context/QuizContext';
import AdminView from '../navigation/AdminView';
import PlayView from '../play/PlayView';
Expand All @@ -31,6 +32,8 @@ const View = (): JSX.Element => {
return <PlayView />;
}
}
case Context.Analytics:
return <AnalyticsView />;
case Context.Player:
default:
return <PlayView />;
Expand Down
1 change: 0 additions & 1 deletion src/config/selectors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ export const TABLE_BY_USER_QUESTION_NAME_HEADER_CY =
export const TABLE_BY_USER_ANSWER_DATA_CY = 'tableByUserAnswerData';
export const TABLE_BY_USER_DATE_DATA_CY = 'tableByUserDateData';
export const TABLE_BY_USER_CORRECT_ICON_CY = 'tableByUserCorrectIcon';
export const NAVIGATION_ANALYTICS_BUTTON_CY = 'navigationAnalyticsButton';
export const ANALYTICS_CONTAINER_CY = 'analyticsContainer';
export const ANALYTICS_GENERAL_TAB_MENU_CY = 'analyticsGeneralTabMenu';
export const buildAnalyticsDetailedQuestionTabMenuCy = (qTitle: string) =>
Expand Down

0 comments on commit a21e06b

Please sign in to comment.