Add internship type management list
This commit is contained in:
parent
4148a78627
commit
96b1dafb65
@ -19,7 +19,9 @@ export const internshipTypeDtoTransformer: Transformer<InternshipTypeDTO, Intern
|
|||||||
description: subject.description ? {
|
description: subject.description ? {
|
||||||
pl: subject.description,
|
pl: subject.description,
|
||||||
en: subject.descriptionEng || ""
|
en: subject.descriptionEng || ""
|
||||||
} : undefined
|
} : undefined,
|
||||||
|
requiresDeanApproval: parseInt(subject.id || "0") == 4,
|
||||||
|
requiresInsurance: parseInt(subject.id || "0") >= 4,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reverseTransform(subject: InternshipType, context?: unknown): InternshipTypeDTO {
|
reverseTransform(subject: InternshipType, context?: unknown): InternshipTypeDTO {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { HTMLProps } from "react";
|
import React, { HTMLProps } from "react";
|
||||||
import { useHorizontalSpacing } from "@/styles";
|
import { useHorizontalSpacing } from "@/styles";
|
||||||
|
|
||||||
type ActionsProps = {
|
export type ActionsProps = {
|
||||||
spacing?: number;
|
spacing?: number;
|
||||||
} & HTMLProps<HTMLDivElement>;
|
} & HTMLProps<HTMLDivElement>;
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ import { Company, Office } from "@/data/company";
|
|||||||
export interface InternshipType extends Identifiable {
|
export interface InternshipType extends Identifiable {
|
||||||
label: Multilingual<string>,
|
label: Multilingual<string>,
|
||||||
description?: Multilingual<string>,
|
description?: Multilingual<string>,
|
||||||
|
requiresDeanApproval: boolean,
|
||||||
|
requiresInsurance: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InternshipProgramEntry extends Identifiable {
|
export interface InternshipProgramEntry extends Identifiable {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import * as edition from "./edition"
|
import * as edition from "./edition"
|
||||||
import * as page from "./page"
|
import * as page from "./page"
|
||||||
|
import * as type from "./type"
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
edition,
|
edition,
|
||||||
page
|
page,
|
||||||
|
type
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
28
src/management/api/type.ts
Normal file
28
src/management/api/type.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { InternshipType } from "@/data";
|
||||||
|
import { axios } from "@/api";
|
||||||
|
import { InternshipTypeDTO, internshipTypeDtoTransformer } from "@/api/dto/type";
|
||||||
|
import { encapsulate, OneOrMany } from "@/helpers";
|
||||||
|
import { prepare } from "@/routing";
|
||||||
|
|
||||||
|
const INTERNSHIP_TYPE_INDEX_ENDPOINT = '/internshipTypes'
|
||||||
|
const INTERNSHIP_TYPE_ENDPOINT = INTERNSHIP_TYPE_INDEX_ENDPOINT + "/:id";
|
||||||
|
|
||||||
|
export async function all(): Promise<InternshipType[]> {
|
||||||
|
const response = await axios.get<InternshipTypeDTO[]>(INTERNSHIP_TYPE_INDEX_ENDPOINT);
|
||||||
|
return response.data.map(dto => internshipTypeDtoTransformer.transform(dto))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function remove(type: OneOrMany<InternshipType>): Promise<void> {
|
||||||
|
await Promise.all(encapsulate(type).map(
|
||||||
|
type => axios.delete(prepare(INTERNSHIP_TYPE_ENDPOINT, { id: type.id as string }))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function save(type: InternshipType): Promise<InternshipType> {
|
||||||
|
await axios.put<InternshipType>(
|
||||||
|
INTERNSHIP_TYPE_INDEX_ENDPOINT,
|
||||||
|
internshipTypeDtoTransformer.reverseTransform(type)
|
||||||
|
);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
15
src/management/common/BulkActions.tsx
Normal file
15
src/management/common/BulkActions.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Actions, ActionsProps } from "@/components";
|
||||||
|
import React from "react";
|
||||||
|
import { Typography } from "@material-ui/core";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
export type BulkActionsProps = ActionsProps;
|
||||||
|
|
||||||
|
export const BulkActions = ({ children, ...props }: BulkActionsProps) => {
|
||||||
|
const { t } = useTranslation("management");
|
||||||
|
|
||||||
|
return <Actions { ...props }>
|
||||||
|
<Typography variant="subtitle2">{ t("actions.bulk") }: </Typography>
|
||||||
|
{ children }
|
||||||
|
</Actions>;
|
||||||
|
};
|
56
src/management/common/DeleteResourceAction.tsx
Normal file
56
src/management/common/DeleteResourceAction.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { OneOrMany } from "@/helpers";
|
||||||
|
import useTheme from "@material-ui/core/styles/useTheme";
|
||||||
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
|
import { Confirm } from "@/components/confirm";
|
||||||
|
import { Button, IconButton, Tooltip } from "@material-ui/core";
|
||||||
|
import { Delete } from "mdi-material-ui";
|
||||||
|
import { createBoundComponent } from "@/management/common/helpers";
|
||||||
|
|
||||||
|
export type DeleteResourceActionProps<T> = {
|
||||||
|
onDelete: (resource: OneOrMany<T>) => void;
|
||||||
|
resource: OneOrMany<T>;
|
||||||
|
label: (resource: T) => string;
|
||||||
|
children?: (action: any) => React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function DeleteResourceAction<T>({ onDelete, resource, children, label }: DeleteResourceActionProps<T>) {
|
||||||
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation("management");
|
||||||
|
|
||||||
|
const confirmation = <>
|
||||||
|
{ !Array.isArray(resource)
|
||||||
|
? <Trans i18nKey="confirm.delete">
|
||||||
|
Czy na pewno chcesz usunąć <strong>{ label(resource) }</strong>?
|
||||||
|
</Trans>
|
||||||
|
: <>
|
||||||
|
{ t("confirm.bulk-delete") }
|
||||||
|
<ul>
|
||||||
|
{ resource.map(current => <li key={ label(current) }>{ label(current) }</li>) }
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</>;
|
||||||
|
|
||||||
|
return <Confirm
|
||||||
|
onConfirm={ () => onDelete(resource) }
|
||||||
|
content={ confirmation }
|
||||||
|
confirm={ props =>
|
||||||
|
<Button variant="contained" startIcon={ <Delete /> }
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.palette.error.dark,
|
||||||
|
color: theme.palette.error.contrastText,
|
||||||
|
}}
|
||||||
|
{ ...props }>
|
||||||
|
{ t("actions.delete") }
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{ action => children ? children(action) : <Tooltip title={ t("actions.delete") as string }><IconButton onClick={ action }><Delete /></IconButton></Tooltip> }
|
||||||
|
</Confirm>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDeleteAction<T>(props: Pick<DeleteResourceActionProps<T>, 'label' | 'onDelete'>) {
|
||||||
|
return createBoundComponent(DeleteResourceAction, props);
|
||||||
|
}
|
||||||
|
|
11
src/management/common/MaterialTableTitle.tsx
Normal file
11
src/management/common/MaterialTableTitle.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { AsyncResult } from "@/hooks";
|
||||||
|
import { CircularProgress } from "@material-ui/core";
|
||||||
|
|
||||||
|
export type MaterialTableTitleProps = { result: AsyncResult<any>, label: React.ReactNode } & React.HTMLProps<HTMLDivElement>;
|
||||||
|
|
||||||
|
export const MaterialTableTitle = ({ label, result, style, ...props }: MaterialTableTitleProps) =>
|
||||||
|
<div style={ { display: "flex", alignItems: "center", ...style } } { ...props }>
|
||||||
|
{ label }
|
||||||
|
{ result.isLoading && <CircularProgress size="1.5rem" style={ { marginLeft: "1rem" } }/> }
|
||||||
|
</div>
|
20
src/management/common/helpers.tsx
Normal file
20
src/management/common/helpers.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Column } from "material-table";
|
||||||
|
import { Actions } from "@/components";
|
||||||
|
import { Trans } from "react-i18next";
|
||||||
|
|
||||||
|
export function actionsColumn<T extends Object>(render: (value: T) => React.ReactNode): Column<T> {
|
||||||
|
return {
|
||||||
|
title: <Trans i18nKey="management:actions.label" />,
|
||||||
|
render: value => <Actions style={{ margin: "-1rem" }} spacing={ 0 }>{ render(value) }</Actions>,
|
||||||
|
sorting: false,
|
||||||
|
width: 0,
|
||||||
|
resizable: false,
|
||||||
|
removable: false,
|
||||||
|
searchable: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createBoundComponent<T, TBoundProps extends keyof T>(Component: React.ComponentType<T>, bound: Pick<T, TBoundProps>) {
|
||||||
|
return (props: Omit<T, TBoundProps>) => <Component { ...bound as any } { ...props } />;
|
||||||
|
}
|
@ -4,7 +4,7 @@ import React from "react";
|
|||||||
import { Link as RouterLink } from "react-router-dom";
|
import { Link as RouterLink } from "react-router-dom";
|
||||||
import { route } from "@/routing";
|
import { route } from "@/routing";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { CalendarClock, FileDocumentMultipleOutline } from "mdi-material-ui";
|
import { CalendarClock, FileCertificateOutline, FileDocumentMultipleOutline } from "mdi-material-ui";
|
||||||
|
|
||||||
export const Management = {
|
export const Management = {
|
||||||
Breadcrumbs: ({ children, ...props }: BreadcrumbsProps) => {
|
Breadcrumbs: ({ children, ...props }: BreadcrumbsProps) => {
|
||||||
@ -41,6 +41,9 @@ export const ManagementIndex = () => {
|
|||||||
<ManagementLink icon={ <CalendarClock /> } route={ route("management:editions") }>
|
<ManagementLink icon={ <CalendarClock /> } route={ route("management:editions") }>
|
||||||
{ t("management:edition.index.title") }
|
{ t("management:edition.index.title") }
|
||||||
</ManagementLink>
|
</ManagementLink>
|
||||||
|
<ManagementLink icon={ <FileCertificateOutline /> } route={ route("management:types") }>
|
||||||
|
{ t("management:type.index.title") }
|
||||||
|
</ManagementLink>
|
||||||
<ManagementLink icon={ <FileDocumentMultipleOutline /> } route={ route("management:static_pages") }>
|
<ManagementLink icon={ <FileDocumentMultipleOutline /> } route={ route("management:static_pages") }>
|
||||||
{ t("management:page.index.title") }
|
{ t("management:page.index.title") }
|
||||||
</ManagementLink>
|
</ManagementLink>
|
||||||
|
@ -18,6 +18,12 @@ import { createPortal } from "react-dom";
|
|||||||
import { EditStaticPageDialog } from "@/management/page/edit";
|
import { EditStaticPageDialog } from "@/management/page/edit";
|
||||||
import { Confirm } from "@/components/confirm";
|
import { Confirm } from "@/components/confirm";
|
||||||
import useTheme from "@material-ui/core/styles/useTheme";
|
import useTheme from "@material-ui/core/styles/useTheme";
|
||||||
|
import { BulkActions } from "@/management/common/BulkActions";
|
||||||
|
import { MaterialTableTitle } from "@/management/common/MaterialTableTitle";
|
||||||
|
import { actionsColumn } from "@/management/common/helpers";
|
||||||
|
import { createDeleteAction } from "@/management/common/DeleteResourceAction";
|
||||||
|
|
||||||
|
const label = (page: StaticPage) => page.title.pl;
|
||||||
|
|
||||||
export const StaticPageManagement = () => {
|
export const StaticPageManagement = () => {
|
||||||
const { t } = useTranslation("management");
|
const { t } = useTranslation("management");
|
||||||
@ -69,46 +75,13 @@ export const StaticPageManagement = () => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteStaticPageAction = ({ page, children }: { page: OneOrMany<StaticPage>, children?: (action: any) => React.ReactNode }) => {
|
const handlePageDeletion = async (page: OneOrMany<StaticPage>) => {
|
||||||
const theme = useTheme();
|
await api.page.remove(page);
|
||||||
|
updatePageList();
|
||||||
const handlePageDeletion = async () => {
|
|
||||||
await api.page.remove(page);
|
|
||||||
updatePageList();
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmation = <>
|
|
||||||
{ !Array.isArray(page)
|
|
||||||
? <Trans i18nKey="page.confirm.delete">
|
|
||||||
Czy na pewno chcesz usunąć stronę <strong>{ page.title.pl }</strong>?
|
|
||||||
</Trans>
|
|
||||||
: <>
|
|
||||||
{ t("page.confirm.bulk-delete") }
|
|
||||||
<ul>
|
|
||||||
{ page.map(page => <li key={ page.slug }>{ page.title.pl }</li>) }
|
|
||||||
</ul>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</>;
|
|
||||||
|
|
||||||
return <Confirm
|
|
||||||
onConfirm={ handlePageDeletion }
|
|
||||||
content={ confirmation }
|
|
||||||
confirm={ props =>
|
|
||||||
<Button variant="contained" startIcon={ <Delete /> }
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.palette.error.dark,
|
|
||||||
color: theme.palette.error.contrastText,
|
|
||||||
}}
|
|
||||||
{ ...props }>
|
|
||||||
{ t("actions.delete") }
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{ action => children ? children(action) : <Tooltip title={ t("actions.delete") as string }><IconButton onClick={ action }><Delete /></IconButton></Tooltip> }
|
|
||||||
</Confirm>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DeleteStaticPageAction = createDeleteAction<StaticPage>({ label, onDelete: handlePageDeletion })
|
||||||
|
|
||||||
const PreviewStaticPageAction = ({ page }: { page: StaticPage }) => {
|
const PreviewStaticPageAction = ({ page }: { page: StaticPage }) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const handlePagePreview = async () => history.push(`/${page.slug}`);
|
const handlePagePreview = async () => history.push(`/${page.slug}`);
|
||||||
@ -127,19 +100,11 @@ export const StaticPageManagement = () => {
|
|||||||
field: "slug",
|
field: "slug",
|
||||||
title: t("page.field.slug"),
|
title: t("page.field.slug"),
|
||||||
},
|
},
|
||||||
{
|
actionsColumn(page => <>
|
||||||
title: t("actions.label"),
|
<EditStaticPageAction page={ page } />
|
||||||
render: page => <Actions style={{ margin: "-1rem" }} spacing={ 0 }>
|
<DeleteStaticPageAction resource={ page } />
|
||||||
<EditStaticPageAction page={ page } />
|
<PreviewStaticPageAction page={ page } />
|
||||||
<DeleteStaticPageAction page={ page } />
|
</>)
|
||||||
<PreviewStaticPageAction page={ page } />
|
|
||||||
</Actions>,
|
|
||||||
sorting: false,
|
|
||||||
width: 0,
|
|
||||||
resizable: false,
|
|
||||||
removable: false,
|
|
||||||
searchable: false,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const PagePreview = ({ page }: { page: StaticPage }) =>
|
const PagePreview = ({ page }: { page: StaticPage }) =>
|
||||||
@ -168,15 +133,14 @@ export const StaticPageManagement = () => {
|
|||||||
<CreateStaticPageAction />
|
<CreateStaticPageAction />
|
||||||
<Button onClick={ updatePageList } startIcon={ <Refresh /> }>{ t("refresh") }</Button>
|
<Button onClick={ updatePageList } startIcon={ <Refresh /> }>{ t("refresh") }</Button>
|
||||||
</Actions>
|
</Actions>
|
||||||
{ selected.length > 0 && <Actions>
|
{ selected.length > 0 && <BulkActions>
|
||||||
<Typography variant="subtitle2">{ t("actions.bulk") }: </Typography>
|
<DeleteStaticPageAction resource={ selected }>
|
||||||
<DeleteStaticPageAction page={ selected }>
|
|
||||||
{ action => <Button startIcon={ <Delete /> } onClick={ action }>{ t("actions.delete") }</Button> }
|
{ action => <Button startIcon={ <Delete /> } onClick={ action }>{ t("actions.delete") }</Button> }
|
||||||
</DeleteStaticPageAction>
|
</DeleteStaticPageAction>
|
||||||
</Actions> }
|
</BulkActions> }
|
||||||
<Async async={ result } keepValue>{
|
<Async async={ result } keepValue>{
|
||||||
pages => <MaterialTable
|
pages => <MaterialTable
|
||||||
title={ <div style={{ display: "flex", alignItems: "center" }}>{ t("page.index.title") } { result.isLoading && <CircularProgress size="1.5rem" style={{ marginLeft: "1rem" }}/> }</div> }
|
title={ <MaterialTableTitle result={ result } label={ t("page.index.title") }/> }
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
data={ pages }
|
data={ pages }
|
||||||
detailPanel={ page => <PagePreview page={ page } /> }
|
detailPanel={ page => <PagePreview page={ page } /> }
|
||||||
|
@ -4,11 +4,13 @@ import { EditionsManagement } from "@/management/edition/list";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { ManagementIndex } from "@/management/main";
|
import { ManagementIndex } from "@/management/main";
|
||||||
import StaticPageManagement from "@/management/page/list";
|
import StaticPageManagement from "@/management/page/list";
|
||||||
|
import { InternshipTypeManagement } from "@/management/type/list";
|
||||||
|
|
||||||
export const managementRoutes: Route[] = ([
|
export const managementRoutes: Route[] = ([
|
||||||
{ name: "index", path: "/", content: ManagementIndex, exact: true },
|
{ name: "index", path: "/", content: ManagementIndex, exact: true },
|
||||||
|
|
||||||
{ name: "editions", path: "/editions", content: EditionsManagement },
|
{ name: "editions", path: "/editions", content: EditionsManagement },
|
||||||
|
{ name: "types", path: "/types", content: InternshipTypeManagement },
|
||||||
{ name: "static_pages", path: "/static-pages", content: StaticPageManagement }
|
{ name: "static_pages", path: "/static-pages", content: StaticPageManagement }
|
||||||
] as Route[]).map(
|
] as Route[]).map(
|
||||||
({ name, path, middlewares = [], ...route }): Route => ({
|
({ name, path, middlewares = [], ...route }): Route => ({
|
||||||
|
110
src/management/type/list.tsx
Normal file
110
src/management/type/list.tsx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { Page } from "@/pages/base";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useAsyncState } from "@/hooks";
|
||||||
|
import { InternshipType, Multilingual } from "@/data";
|
||||||
|
import api from "@/management/api";
|
||||||
|
import { Management } from "@/management/main";
|
||||||
|
import { Button, Chip, Container, Tooltip, Typography } from "@material-ui/core";
|
||||||
|
import { Async } from "@/components/async";
|
||||||
|
import MaterialTable, { Column } from "material-table";
|
||||||
|
import { MaterialTableTitle } from "@/management/common/MaterialTableTitle";
|
||||||
|
import { actionsColumn } from "@/management/common/helpers";
|
||||||
|
import { AccountCheck, Delete, Refresh, ShieldCheck } from "mdi-material-ui";
|
||||||
|
import { OneOrMany } from "@/helpers";
|
||||||
|
import { createDeleteAction } from "@/management/common/DeleteResourceAction";
|
||||||
|
import { BulkActions } from "@/management/common/BulkActions";
|
||||||
|
import { useSpacing } from "@/styles";
|
||||||
|
import { Actions } from "@/components";
|
||||||
|
|
||||||
|
const title = "type.index.title";
|
||||||
|
|
||||||
|
const MultilingualCell = ({ value }: { value: Multilingual<React.ReactNode> }) => {
|
||||||
|
return <>
|
||||||
|
{ Object.keys(value).map(language => <div>
|
||||||
|
<Chip size="small" label={ language.toUpperCase() } style={ { marginRight: "0.5rem" } }/>
|
||||||
|
{ value[language as keyof Multilingual<any>] }
|
||||||
|
</div>) }
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const label = (type: InternshipType) => type?.label?.pl;
|
||||||
|
|
||||||
|
export const InternshipTypeManagement = () => {
|
||||||
|
const { t } = useTranslation("management");
|
||||||
|
const [result, setTypesPromise] = useAsyncState<InternshipType[]>();
|
||||||
|
const [selected, setSelected] = useState<InternshipType[]>([]);
|
||||||
|
const spacing = useSpacing(2);
|
||||||
|
|
||||||
|
const updateTypeList = () => {
|
||||||
|
setTypesPromise(api.type.all());
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleTypeDelete = async (type: OneOrMany<InternshipType>) => {
|
||||||
|
await api.type.remove(type);
|
||||||
|
updateTypeList();
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(updateTypeList, []);
|
||||||
|
|
||||||
|
const DeleteTypeAction = createDeleteAction({ label, onDelete: handleTypeDelete });
|
||||||
|
|
||||||
|
const columns: Column<InternshipType>[] = [
|
||||||
|
{
|
||||||
|
field: "id",
|
||||||
|
title: "ID",
|
||||||
|
width: 0,
|
||||||
|
defaultSort: "asc",
|
||||||
|
filtering: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("type.field.label"),
|
||||||
|
render: type => <MultilingualCell value={ type.label }/>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("type.field.description"),
|
||||||
|
render: type => type.description && <MultilingualCell value={ type.description }/>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("type.field.flags"),
|
||||||
|
render: type => <>
|
||||||
|
{ type.requiresDeanApproval && <Tooltip title={ t("type.flag.dean-approval") as string }><AccountCheck/></Tooltip> }
|
||||||
|
{ type.requiresInsurance && <Tooltip title={ t("type.flag.insurance") as string }><ShieldCheck/></Tooltip> }
|
||||||
|
</>,
|
||||||
|
width: 0,
|
||||||
|
filtering: true,
|
||||||
|
sorting: false,
|
||||||
|
},
|
||||||
|
actionsColumn(type => <>
|
||||||
|
<DeleteTypeAction resource={ type }/>
|
||||||
|
</>)
|
||||||
|
];
|
||||||
|
|
||||||
|
return <Page>
|
||||||
|
<Page.Header maxWidth="lg">
|
||||||
|
<Management.Breadcrumbs>
|
||||||
|
<Typography color="textPrimary">{ t(title) }</Typography>
|
||||||
|
</Management.Breadcrumbs>
|
||||||
|
<Page.Title>{ t(title) }</Page.Title>
|
||||||
|
</Page.Header>
|
||||||
|
<Container maxWidth="lg" className={ spacing.vertical }>
|
||||||
|
<Actions>
|
||||||
|
<Button onClick={ updateTypeList } startIcon={ <Refresh /> }>{ t("refresh") }</Button>
|
||||||
|
</Actions>
|
||||||
|
{ selected.length > 0 && <BulkActions>
|
||||||
|
<DeleteTypeAction resource={ selected }>
|
||||||
|
{ action => <Button startIcon={ <Delete /> } onClick={ action }>{ t("actions.delete") }</Button> }
|
||||||
|
</DeleteTypeAction>
|
||||||
|
</BulkActions> }
|
||||||
|
<Async async={ result } keepValue>{
|
||||||
|
pages => <MaterialTable
|
||||||
|
title={ <MaterialTableTitle result={ result } label={ t(title) }/> }
|
||||||
|
columns={ columns }
|
||||||
|
data={ pages }
|
||||||
|
onSelectionChange={ pages => setSelected(pages) }
|
||||||
|
options={ { selection: true, pageSize: 10 } }
|
||||||
|
/>
|
||||||
|
}</Async>
|
||||||
|
</Container>
|
||||||
|
</Page>
|
||||||
|
}
|
@ -21,6 +21,17 @@ edition:
|
|||||||
end: Koniec
|
end: Koniec
|
||||||
course: Kierunek
|
course: Kierunek
|
||||||
|
|
||||||
|
type:
|
||||||
|
index:
|
||||||
|
title: "Rodzeje praktyki"
|
||||||
|
field:
|
||||||
|
label: "Rodzaj praktyki"
|
||||||
|
description: "Opis"
|
||||||
|
flags: "Flagi"
|
||||||
|
flag:
|
||||||
|
dean-approval: "Wymaga zgody dziekana"
|
||||||
|
insurance: "Wymaga ubezpieczenia"
|
||||||
|
|
||||||
page:
|
page:
|
||||||
index:
|
index:
|
||||||
title: Strony statyczne
|
title: Strony statyczne
|
||||||
|
Loading…
Reference in New Issue
Block a user