fix(ui): uxt fixes
This commit is contained in:
parent
27ee9461af
commit
d054e39165
4 changed files with 91 additions and 86 deletions
|
|
@ -66,7 +66,6 @@ function TestEdit() {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
uxtestingStore.createNewTest(isPreview).then((test) => {
|
uxtestingStore.createNewTest(isPreview).then((test) => {
|
||||||
console.log(test);
|
|
||||||
if (isPreview) {
|
if (isPreview) {
|
||||||
window.open(`${test.startingPath}?oruxt=${test.testId}`, '_blank', 'noopener,noreferrer');
|
window.open(`${test.startingPath}?oruxt=${test.testId}`, '_blank', 'noopener,noreferrer');
|
||||||
history.push(withSiteId(usabilityTestingEdit(test.testId), siteId));
|
history.push(withSiteId(usabilityTestingEdit(test.testId), siteId));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { durationFormatted } from 'App/date';
|
import { durationFormatted } from 'App/date';
|
||||||
import usePageTitle from "App/hooks/usePageTitle";
|
import usePageTitle from 'App/hooks/usePageTitle';
|
||||||
import { numberWithCommas } from 'App/utils';
|
import { numberWithCommas } from 'App/utils';
|
||||||
import { getPdf2 } from 'Components/AssistStats/pdfGenerator';
|
import { getPdf2 } from 'Components/AssistStats/pdfGenerator';
|
||||||
import { useModal } from 'Components/Modal';
|
import { useModal } from 'Components/Modal';
|
||||||
|
|
@ -36,10 +36,10 @@ import ResponsesOverview from './ResponsesOverview';
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
const statusItems = [
|
const statusItems = [
|
||||||
{ value: 'preview', label: 'Preview', icon: <HourglassOutlined rev={undefined} /> },
|
{ value: 'preview', label: 'Draft', icon: <HourglassOutlined rev={undefined} /> },
|
||||||
{ value: 'in-progress', label: 'In Progress', icon: <HourglassOutlined rev={undefined} /> },
|
{ value: 'in-progress', label: 'Ongoing', icon: <HourglassOutlined rev={undefined} /> },
|
||||||
{ value: 'paused', label: 'Pause', icon: <PauseCircleOutlined rev={undefined} /> },
|
{ value: 'paused', label: 'On Hold', icon: <PauseCircleOutlined rev={undefined} /> },
|
||||||
{ value: 'closed', label: 'End Testing', icon: <StopOutlined rev={undefined} /> },
|
{ value: 'closed', label: 'Closed', icon: <StopOutlined rev={undefined} /> },
|
||||||
];
|
];
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
|
|
@ -71,7 +71,6 @@ function TestOverview() {
|
||||||
uxtestingStore.getTest(testId);
|
uxtestingStore.getTest(testId);
|
||||||
}, [testId]);
|
}, [testId]);
|
||||||
|
|
||||||
|
|
||||||
if (!uxtestingStore.instance) {
|
if (!uxtestingStore.instance) {
|
||||||
return <Loader loading={uxtestingStore.isLoading}>No data.</Loader>;
|
return <Loader loading={uxtestingStore.isLoading}>No data.</Loader>;
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +80,7 @@ function TestOverview() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full mx-auto" style={{ maxWidth: '1360px'}}>
|
<div className="w-full mx-auto" style={{ maxWidth: '1360px' }}>
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
|
|
@ -117,7 +116,6 @@ function TestOverview() {
|
||||||
<ParticipantOverview />
|
<ParticipantOverview />
|
||||||
<TaskSummary />
|
<TaskSummary />
|
||||||
|
|
||||||
|
|
||||||
<div className={'mt-2 rounded border p-4 bg-white flex gap-2 items-center'}>
|
<div className={'mt-2 rounded border p-4 bg-white flex gap-2 items-center'}>
|
||||||
<Typography.Title style={{ marginBottom: 0 }} level={5}>
|
<Typography.Title style={{ marginBottom: 0 }} level={5}>
|
||||||
Open-ended task responses
|
Open-ended task responses
|
||||||
|
|
@ -192,9 +190,7 @@ const ParticipantOverview = observer(() => {
|
||||||
<UserOutlined style={{ fontSize: 18, color: '#394EFF' }} rev={undefined} />
|
<UserOutlined style={{ fontSize: 18, color: '#394EFF' }} rev={undefined} />
|
||||||
<Typography.Text strong>Total Participants</Typography.Text>
|
<Typography.Text strong>Total Participants</Typography.Text>
|
||||||
</div>
|
</div>
|
||||||
<Typography.Title level={5}>
|
<Typography.Title level={5}>{uxtestingStore.testStats.tests_attempts}</Typography.Title>
|
||||||
{uxtestingStore.testStats.tests_attempts}
|
|
||||||
</Typography.Title>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={'rounded border p-2 flex-1'}>
|
<div className={'rounded border p-2 flex-1'}>
|
||||||
<div className={'flex items-center gap-2'}>
|
<div className={'flex items-center gap-2'}>
|
||||||
|
|
@ -207,7 +203,7 @@ const ParticipantOverview = observer(() => {
|
||||||
{Math.round(
|
{Math.round(
|
||||||
(uxtestingStore.testStats.completed_all_tasks /
|
(uxtestingStore.testStats.completed_all_tasks /
|
||||||
uxtestingStore.testStats.tests_attempts) *
|
uxtestingStore.testStats.tests_attempts) *
|
||||||
100
|
100
|
||||||
)}
|
)}
|
||||||
%
|
%
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
|
|
@ -226,7 +222,7 @@ const ParticipantOverview = observer(() => {
|
||||||
{Math.round(
|
{Math.round(
|
||||||
(uxtestingStore.testStats.tasks_skipped /
|
(uxtestingStore.testStats.tasks_skipped /
|
||||||
uxtestingStore.testStats.tests_attempts) *
|
uxtestingStore.testStats.tests_attempts) *
|
||||||
100
|
100
|
||||||
)}
|
)}
|
||||||
%
|
%
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
|
|
@ -245,7 +241,7 @@ const ParticipantOverview = observer(() => {
|
||||||
{Math.round(
|
{Math.round(
|
||||||
(uxtestingStore.testStats.tests_skipped /
|
(uxtestingStore.testStats.tests_skipped /
|
||||||
uxtestingStore.testStats.tests_attempts) *
|
uxtestingStore.testStats.tests_attempts) *
|
||||||
100
|
100
|
||||||
)}
|
)}
|
||||||
%
|
%
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
|
|
@ -257,8 +253,8 @@ const ParticipantOverview = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
const TaskSummary = observer(() => {
|
const TaskSummary = observer(() => {
|
||||||
const { uxtestingStore } = useStore();
|
const { uxtestingStore } = useStore();
|
||||||
|
|
@ -273,11 +269,11 @@ const TaskSummary = observer(() => {
|
||||||
<Typography.Text strong>
|
<Typography.Text strong>
|
||||||
{uxtestingStore.taskStats
|
{uxtestingStore.taskStats
|
||||||
? durationFormatted(
|
? durationFormatted(
|
||||||
uxtestingStore.taskStats.reduce(
|
uxtestingStore.taskStats.reduce(
|
||||||
(stats, task) => stats + task.avgCompletionTime,
|
(stats, task) => stats + task.avgCompletionTime,
|
||||||
0
|
0
|
||||||
) / uxtestingStore.taskStats.length
|
) / uxtestingStore.taskStats.length
|
||||||
)
|
)
|
||||||
: null}
|
: null}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<ClockCircleOutlined rev={undefined} />
|
<ClockCircleOutlined rev={undefined} />
|
||||||
|
|
@ -289,8 +285,8 @@ const TaskSummary = observer(() => {
|
||||||
<Stage stage={tst} uxt index={index + 1} />
|
<Stage stage={tst} uxt index={index + 1} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
const Title = observer(({ testId, siteId }: any) => {
|
const Title = observer(({ testId, siteId }: any) => {
|
||||||
const { uxtestingStore } = useStore();
|
const { uxtestingStore } = useStore();
|
||||||
|
|
@ -333,65 +329,67 @@ const Title = observer(({ testId, siteId }: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'p-4 flex items-center gap-2 border-b'}>
|
<div className={'p-4 border-b'}>
|
||||||
<div>
|
<div className={'flex items-center gap-2'}>
|
||||||
<Typography.Title level={4}>{uxtestingStore.instance!.title}</Typography.Title>
|
<Typography.Title level={4}>{uxtestingStore.instance!.title}</Typography.Title>
|
||||||
<div className={'text-disabled-text'}>{uxtestingStore.instance!.description}</div>
|
<div className={'ml-auto'} />
|
||||||
</div>
|
<Select
|
||||||
<div className={'ml-auto'} />
|
value={uxtestingStore.instance!.status}
|
||||||
<Select
|
style={{ width: 150 }}
|
||||||
value={uxtestingStore.instance!.status}
|
onChange={handleChange}
|
||||||
style={{ width: 150 }}
|
>
|
||||||
onChange={handleChange}
|
{statusItems.map((item) => (
|
||||||
>
|
<Option key={item.value} value={item.value} label={item.label}>
|
||||||
{statusItems.map((item) => (
|
<Space align={'center'}>
|
||||||
<Option key={item.value} value={item.value} label={item.label}>
|
{item.icon} {item.label}
|
||||||
<Space align={'center'}>
|
</Space>
|
||||||
{item.icon} {item.label}
|
</Option>
|
||||||
</Space>
|
))}
|
||||||
</Option>
|
</Select>
|
||||||
))}
|
<Button type={'primary'} onClick={redirectToEdit}>
|
||||||
</Select>
|
|
||||||
<Button type={'primary'} onClick={redirectToEdit}>
|
|
||||||
<Space align={'center'}>
|
|
||||||
{uxtestingStore.instance!.tasks.length} Tasks <EditOutlined rev={undefined} />{' '}
|
|
||||||
</Space>
|
|
||||||
</Button>
|
|
||||||
<Popover
|
|
||||||
trigger={'click'}
|
|
||||||
title={'Participants Link'}
|
|
||||||
content={
|
|
||||||
<div style={{ width: '220px' }}>
|
|
||||||
<div className={'p-2 bg-white rounded border break-all mb-2'}>
|
|
||||||
{`${uxtestingStore.instance!.startingPath}?oruxt=${
|
|
||||||
uxtestingStore.instance!.testId
|
|
||||||
}`}
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
copy(
|
|
||||||
`${uxtestingStore.instance!.startingPath}?oruxt=${
|
|
||||||
uxtestingStore.instance!.testId
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Copy
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Button type={'primary'} ghost>
|
|
||||||
<Space align={'center'}>
|
<Space align={'center'}>
|
||||||
Distribute
|
{uxtestingStore.instance!.tasks.length} Tasks <EditOutlined rev={undefined} />{' '}
|
||||||
<ShareAltOutlined rev={undefined} />
|
|
||||||
</Space>
|
</Space>
|
||||||
</Button>
|
</Button>
|
||||||
</Popover>
|
<Popover
|
||||||
<Dropdown menu={{ items: menuItems, onClick: onMenuClick }}>
|
trigger={'click'}
|
||||||
<Button icon={<MoreOutlined rev={undefined} />}></Button>
|
title={'Participants Link'}
|
||||||
</Dropdown>
|
content={
|
||||||
|
<div style={{ width: '220px' }}>
|
||||||
|
<div className={'p-2 bg-white rounded border break-all mb-2'}>
|
||||||
|
{`${uxtestingStore.instance!.startingPath}?oruxt=${
|
||||||
|
uxtestingStore.instance!.testId
|
||||||
|
}`}
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
copy(
|
||||||
|
`${uxtestingStore.instance!.startingPath}?oruxt=${
|
||||||
|
uxtestingStore.instance!.testId
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Copy
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button type={'primary'} ghost>
|
||||||
|
<Space align={'center'}>
|
||||||
|
Distribute
|
||||||
|
<ShareAltOutlined rev={undefined} />
|
||||||
|
</Space>
|
||||||
|
</Button>
|
||||||
|
</Popover>
|
||||||
|
<Dropdown menu={{ items: menuItems, onClick: onMenuClick }}>
|
||||||
|
<Button icon={<MoreOutlined rev={undefined} />}></Button>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
<div className={'text-disabled-text whitespace-pre-wrap'}>
|
||||||
|
{uxtestingStore.instance!.description}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
export default observer(TestOverview);
|
export default observer(TestOverview);
|
||||||
|
|
|
||||||
|
|
@ -172,21 +172,22 @@ const statusMap = {
|
||||||
preview: "Preview",
|
preview: "Preview",
|
||||||
'in-progress': "In progress",
|
'in-progress': "In progress",
|
||||||
paused: "Paused",
|
paused: "Paused",
|
||||||
completed: "Completed",
|
closed: "Completed",
|
||||||
}
|
}
|
||||||
|
|
||||||
function Row({ test }: { test: UxTListEntry }) {
|
function Row({ test }: { test: UxTListEntry }) {
|
||||||
const link = usabilityTestingView(test.testId.toString())
|
const link = usabilityTestingView(test.testId.toString())
|
||||||
|
const editLink = usabilityTestingEdit(test.testId.toString())
|
||||||
return (
|
return (
|
||||||
<div className={'grid grid-cols-8 p-4 border-b hover:bg-active-blue'}>
|
<div className={'grid grid-cols-8 p-4 border-b hover:bg-active-blue'}>
|
||||||
<Cell size={4}>
|
<Cell size={4}>
|
||||||
<div className={'flex items-center gap-2'}>
|
<div className={'flex items-center gap-2'}>
|
||||||
<Avatar size={'large'} icon={<UnorderedListOutlined rev={undefined} />} />
|
<Avatar size={'large'} icon={<UnorderedListOutlined rev={undefined} />} />
|
||||||
<div>
|
<div style={{ maxWidth: 550 }}>
|
||||||
<Link className='link' to={link}>
|
<Link className='link' to={test.status === 'preview' ? editLink : link}>
|
||||||
{test.title}
|
{test.title}
|
||||||
</Link>
|
</Link>
|
||||||
<div className={'text-disabled-text'}>
|
<div className={'text-disabled-text whitespace-nowrap text-ellipsis overflow-hidden'}>
|
||||||
{test.description}
|
{test.description}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -195,12 +196,19 @@ function Row({ test }: { test: UxTListEntry }) {
|
||||||
<Cell size={1}>{test.createdBy.name}</Cell>
|
<Cell size={1}>{test.createdBy.name}</Cell>
|
||||||
<Cell size={2}>{checkForRecent(getDateFromMill(test.updatedAt)!, 'LLL dd, yyyy, hh:mm a')}</Cell>
|
<Cell size={2}>{checkForRecent(getDateFromMill(test.updatedAt)!, 'LLL dd, yyyy, hh:mm a')}</Cell>
|
||||||
<Cell size={1}>
|
<Cell size={1}>
|
||||||
<Tag color={test.status === 'in-progress' ? "orange" : ''}>{statusMap[test.status]}</Tag>
|
<Tag color={colors[test.status]}>{statusMap[test.status]}</Tag>
|
||||||
</Cell>
|
</Cell>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const colors = {
|
||||||
|
'in-progress': 'green',
|
||||||
|
closed: 'geekblue',
|
||||||
|
paused: 'grey',
|
||||||
|
preview: 'orange',
|
||||||
|
} as const
|
||||||
|
|
||||||
function Cell({ size, children }: { size: number; children?: React.ReactNode }) {
|
function Cell({ size, children }: { size: number; children?: React.ReactNode }) {
|
||||||
return <div className={`col-span-${size}`}>{children}</div>;
|
return <div className={`col-span-${size}`}>{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export interface UxTest {
|
||||||
|
|
||||||
export interface UxTListEntry {
|
export interface UxTListEntry {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
status: 'preview' | 'in-progress' | 'paused' | 'completed';
|
status: 'preview' | 'in-progress' | 'paused' | 'closed';
|
||||||
createdBy: {
|
createdBy: {
|
||||||
userId: number;
|
userId: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue