Skip to content

Commit

Permalink
feat: cloud device list ui (#509)
Browse files Browse the repository at this point in the history
* feat: retrieve cloud devices

* wip: cloud device retrieve apis

* wip: cloud device list ui

* feat: add device image

* fix: margin for text

* fix: cloud device list
  • Loading branch information
Ikalli authored Oct 11, 2023
1 parent 8b4876c commit a67c019
Show file tree
Hide file tree
Showing 24 changed files with 755 additions and 179 deletions.
7 changes: 7 additions & 0 deletions packages/typescript-private/console/src/base/cloud-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ export interface CloudDeviceBaseTraits {
export type CloudDeviceBase = CloudDeviceBaseTraits & CloudDeviceRelationTraits;
export const CloudDevicePropCamel = propertiesOf<CloudDeviceBase>();
export const CloudDevicePropSnake = camelToSnakeCasePropertiesOf<CloudDeviceBase>();

export type CloudDeviceMetadataBase = Pick<
DeviceBase,
'location' | 'model' | 'modelName' | 'manufacturer' | 'resolutionWidth' | 'resolutionHeight' | 'memory' | 'platform' | 'usageState'
>;

export type CloudDeviceByModelResponse = Pick<DeviceBase, 'version' | 'model' | 'usageState'>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { PageDtoBase } from '../pagination/page.dto';

export interface FindCloudDevicesDtoBase extends PageDtoBase {}
1 change: 1 addition & 0 deletions packages/typescript-private/console/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export * from './base/user-email-preference';
export * from './base/user-key';
export * from './base/user-sns';
export * from './dto/change-log/change-log.dto';
export * from './dto/cloud-device/cloud-device.dto';
export * from './dto/device-tag/device-tag.dto';
export * from './dto/device/device-response.dto';
export * from './dto/device/device.dto';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const RecordTesting = ({ organization, me, project, deviceId }: Props) => {

return (
<DeviceStreamingLayout
project={project}
organization={organization}
deviceId={deviceId}
right={caseId ? <RecordTestingEditor /> : <RecordTestingEntry project={project} />}
title="Record Testing"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ import { flexRowCenteredStyle } from '../../../src/styles/box';

interface Props {
children: React.ReactNode;
project: ProjectBase;
// project: ProjectBase;
deviceId: DeviceId | null;
editionType: EDITION_TYPE;
}

const StudioLayout = ({ children, project, deviceId, editionType }: Props) => {
const StudioLayout = ({ children, deviceId, editionType }: Props) => {
const router = useRouter();

return (
<>
<Head>
<title>Studio - {project.name} | Dogu</title>
<title>Studio - {deviceId} | Dogu</title>
</Head>
<Box>
<Header
Expand All @@ -36,7 +36,7 @@ const StudioLayout = ({ children, project, deviceId, editionType }: Props) => {
}
/>
<FlexRow>
<Side>
{/* <Side>
<Tooltip title="Manual Testing" placement="right">
<StyledLink
href={{
Expand All @@ -56,7 +56,7 @@ const StudioLayout = ({ children, project, deviceId, editionType }: Props) => {
</IconWrapper>
</StyledLink>
</Tooltip>
{/* <Tooltip title="Record Testing" placement="right">
<Tooltip title="Record Testing" placement="right">
<StyledLink
href={{
pathname: '/dashboard/[orgId]/projects/[pid]/studio/[deviceId]/record',
Expand All @@ -70,8 +70,8 @@ const StudioLayout = ({ children, project, deviceId, editionType }: Props) => {
<BiVideoRecording style={{ fontSize: '1.5rem' }} />
</IconWrapper>
</StyledLink>
</Tooltip> */}
</Side>
</Tooltip>
</Side> */}
<Main>{children}</Main>
</FlexRow>
</Box>
Expand Down
45 changes: 39 additions & 6 deletions projects/console-web-front/enterprise/pages/studio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ export interface StudioTestingPageProps {
feature: FeatureTableBase;
}

export const getStudioTestingLayout = (page: React.ReactElement<StudioTestingPageProps>) => {
export interface CloudStudioTestingPageProps extends Omit<StudioTestingPageProps, 'project'> {}

export const getStudioTestingLayout = (
page: React.ReactElement<StudioTestingPageProps | CloudStudioTestingPageProps>,
) => {
return (
<StudioLayout
editionType={page.props.feature.defaultEdition}
project={page.props.project}
deviceId={page.props.deviceId}
>
<StudioLayout editionType={page.props.feature.defaultEdition} deviceId={page.props.deviceId}>
{page}
</StudioLayout>
);
Expand Down Expand Up @@ -60,3 +60,36 @@ export const getStudioTestingServerSideProps: GetServerSideProps<StudioTestingPa
};
}
};

export const getCloudDeviceStudioTestingServerSideProps: GetServerSideProps<CloudStudioTestingPageProps> = async (
context,
) => {
const deviceId = context.query.deviceId as DeviceId | undefined;

if (!deviceId) {
return {
notFound: true,
};
}

try {
const [organization, user, featureConfig] = await Promise.all([
getOrganizationInServerSide(context),
getUserInServerSide(context),
getFeatureConfigInServerSide(context),
]);

return {
props: {
organization,
me: user,
deviceId,
feature: featureConfig,
},
};
} catch (e) {
return {
notFound: true,
};
}
};
1 change: 1 addition & 0 deletions projects/console-web-front/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"/dashboard/[orgId]/device-farm/standby-devices": ["organization", "device-farm"],
"/dashboard/[orgId]/device-farm/hosts": ["organization", "device-farm"],
"/dashboard/[orgId]/device-farm/tags": ["organization", "device-farm"],
"/dashboard/[orgId]/live-testing": ["organization"],

"/dashboard/[orgId]/projects/[pid]": ["project"],
"/dashboard/[orgId]/projects/[pid]/members": ["project", "project-member"],
Expand Down
1 change: 1 addition & 0 deletions projects/console-web-front/locales/en/organization.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sidebarSubTitle": "Organization",
"liveTestingPageTitle": "Live Testing",
"projectPageTitle": "Projects",
"memberPageTitle": "Members",
"deviceFarmPageTitle": "Device Farm",
Expand Down
1 change: 1 addition & 0 deletions projects/console-web-front/locales/ko/organization.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"sidebarSubTitle": "조직",
"liveTestingPageTitle": "라이브 테스트",
"projectPageTitle": "프로젝트",
"memberPageTitle": "멤버",
"deviceFarmPageTitle": "디바이스 팜",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { GetServerSideProps } from 'next';
import styled from 'styled-components';

import { NextPageWithLayout } from 'pages/_app';
import ManualTesting from 'src/components/studio/ManualTesting';
import {
getCloudDeviceStudioTestingServerSideProps,
getStudioTestingLayout,
CloudStudioTestingPageProps,
} from 'enterprise/pages/studio';

const CloudLiveTestingStudioPage: NextPageWithLayout<CloudStudioTestingPageProps> = ({
organization,
me,
deviceId,
}) => {
return (
<Box>
<ManualTesting organization={organization} deviceId={deviceId} me={me} hideDeviceSelector />
</Box>
);
};

CloudLiveTestingStudioPage.getLayout = getStudioTestingLayout;

export const getServerSideProps: GetServerSideProps<CloudStudioTestingPageProps> =
getCloudDeviceStudioTestingServerSideProps;

export default CloudLiveTestingStudioPage;

const Box = styled.div`
width: 100%;
display: flex;
align-items: flex-start;
flex: 1;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import styled from 'styled-components';
import Head from 'next/head';
import { Divider } from 'antd';

import { NextPageWithLayout } from 'pages/_app';
import ConsoleLayout from 'src/components/layouts/ConsoleLayout';
import OrganizationSideBar from 'src/components/layouts/OrganizationSideBar';
import { getOrganizationPageServerSideProps, OrganizationServerSideProps } from 'src/ssr/organization';
import TableListView from '../../../../src/components/common/TableListView';
import RefreshButton from '../../../../src/components/buttons/RefreshButton';
import { flexRowSpaceBetweenStyle } from '../../../../src/styles/box';
import LiveChat from '../../../../src/components/external/livechat';
import LiveTestingCloudDeviceList from '../../../../src/components/cloud/LiveTestingCloudDeviceList';

const OrganizationLiveTestingPage: NextPageWithLayout<OrganizationServerSideProps> = ({ user, organization }) => {
const hasUsingDevices = true;

return (
<>
<Head>
<title>Live Testing - {organization.name} | Dogu</title>
</Head>
{hasUsingDevices && (
<>
<TableListView
top={
<FlexBox>
<div></div>
<RefreshButton />
</FlexBox>
}
table={<div>Using...</div>}
/>
<Divider />
</>
)}
<TableListView
top={
<FlexBox>
<div></div>
<RefreshButton />
</FlexBox>
}
table={<LiveTestingCloudDeviceList />}
/>
<LiveChat
user={{
name: user.name,
email: user.email,
organizationId: organization.organizationId,
}}
/>
</>
);
};

OrganizationLiveTestingPage.getLayout = (page) => {
return (
<ConsoleLayout {...page.props} sidebar={<OrganizationSideBar />} titleI18nKey="organization:liveTestingPageTitle">
{page}
</ConsoleLayout>
);
};

export const getServerSideProps = getOrganizationPageServerSideProps;

export default OrganizationLiveTestingPage;

const FlexBox = styled.div`
${flexRowSpaceBetweenStyle}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
const StudioManualPage: NextPageWithLayout<StudioTestingPageProps> = ({ organization, project, me, deviceId }) => {
return (
<Box>
<ManualTesting organization={organization} project={project} deviceId={deviceId} me={me} />
<ManualTesting organization={organization} deviceId={deviceId} me={me} />
</Box>
);
};
Expand Down
22 changes: 22 additions & 0 deletions projects/console-web-front/src/api/cloud-device.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { DeviceBase } from '@dogu-private/console';
import { GetServerSidePropsContext } from 'next';

import api from '.';
import { EmptyTokenError, getServersideCookies } from '../utils/auth';

export const getCloudDeviceByIdInServerSide = async (context: GetServerSidePropsContext, deviceId: string) => {
const { authToken } = getServersideCookies(context.req.cookies);

if (authToken) {
try {
const response = await api.get<DeviceBase>(`/cloud-devices/${deviceId}`, {
headers: { Authorization: `Bearer ${authToken}` },
});
return response.data;
} catch (e) {
return null;
}
}

throw new EmptyTokenError();
};
23 changes: 23 additions & 0 deletions projects/console-web-front/src/api/device.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { AttachTagToDeviceDtoBase, DeviceBase, UpdateDeviceDtoBase } from '@dogu-private/console';
import { DeviceId, DeviceTagId, HostId, OrganizationId, ProjectId } from '@dogu-private/types';
import { GetServerSidePropsContext } from 'next';

import api from 'src/api';
import { EmptyTokenError, getServersideCookies } from '../utils/auth';

export const getDeviceCpuRuntimeInfo = async (organizationId: OrganizationId, hostId: HostId, deviceId: string) => {
const query = new URLSearchParams({
Expand Down Expand Up @@ -76,3 +78,24 @@ export const removeDeviceFromProject = async (
await api.delete<void>(`/organizations/${organizationId}/devices/${deviceId}/projects/${projectId}`);
return;
};

export const getDeviceByIdInServerSide = async (
context: GetServerSidePropsContext,
organizationId: OrganizationId,
deviceId: DeviceId,
) => {
const { authToken } = getServersideCookies(context.req.cookies);

if (authToken) {
try {
const response = await api.get<DeviceBase>(`/organizations/${organizationId}/devices/${deviceId}`, {
headers: { Authorization: `Bearer ${authToken}` },
});
return response.data;
} catch (e) {
return null;
}
}

throw new EmptyTokenError();
};
Loading

0 comments on commit a67c019

Please sign in to comment.