react-router-dom#match TypeScript Examples
The following examples show how to use
react-router-dom#match.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: routing.ts From metaflow-ui with Apache License 2.0 | 6 votes |
/**
* Returns parameters from given path (if matching to our defined routes)
* @param pathname location.pathname
*/
export function getRouteMatch(pathname: string): match<KnownURLParams> | null {
return matchPath<KnownURLParams>(
pathname,
Object.keys(SHORT_PATHS).map((key) => SHORT_PATHS[key as keyof PathDefinition]),
);
}
Example #2
Source File: root.component.test.tsx From openmrs-esm-patient-registration with MIT License | 6 votes |
describe('root component', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(
<Root
savePatientForm={jest.fn()}
match={sampleMatchProp}
addressTemplate={{ results: [] }}
currentSession={{} as any}
patientIdentifiers={[]}
relationshipTypes={{ results: [] }}
/>,
div,
);
});
});
Example #3
Source File: patient-registration.test.tsx From openmrs-esm-patient-registration with MIT License | 6 votes |
describe('patient registration sections', () => {
const testSectionExists = (labelText: string) => {
it(labelText + ' exists', async () => {
render(
<ResourcesContext.Provider value={mockResourcesContextValue}>
<PatientRegistration match={sampleMatchProp} savePatientForm={jest.fn()} />
</ResourcesContext.Provider>,
);
await wait();
expect(screen.getByLabelText(labelText)).not.toBeNull();
});
};
beforeAll(() => {
spyOn(mockOpenmrsFramework, 'useConfig').and.returnValue(mockOpenmrsConfig);
});
testSectionExists('Demographics Section');
testSectionExists('Contact Info Section');
});
Example #4
Source File: patient-registration.test.tsx From openmrs-esm-patient-registration with MIT License | 6 votes |
describe('patient registration', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(
<ResourcesContext.Provider value={mockResourcesContextValue}>
<PatientRegistration match={sampleMatchProp} savePatientForm={jest.fn()} />
</ResourcesContext.Provider>,
div,
);
});
});
Example #5
Source File: Team.tsx From js-ts-monorepos with BSD 2-Clause "Simplified" License | 6 votes |
Team: React.FunctionComponent<{ team: ITeam }> = ({ team }) => {
console.log(
`%c TEAM render: ${team.name}`,
"background-color: blue; color: white"
);
const { channels } = team;
return (
<div className="flex-1 flex">
<TeamSidebar team={team} />
<Switch>
<Route exact path={`/team/${team.id}`}>
<h3>Please select a channel</h3>
</Route>
<Route
exact
path={`/team/${team.id}/channel/:channelId`}
children={({ match }: { match: match<{ channelId: string }> }) => (
<SelectedChannel match={match} channels={channels} />
)}
/>
</Switch>
</div>
);
}
Example #6
Source File: App.tsx From js-ts-monorepos with BSD 2-Clause "Simplified" License | 6 votes |
App: React.FunctionComponent = () => {
const [teams, setTeams] = useState<ITeam[]>();
useAsyncDataEffect(() => getAllTeams(), {
setter: setTeams,
stateName: "teams",
});
if (!teams) return <Loading message="Loading teams" />;
return (
<Router>
<div className="flex flex-col sm:flex-row w-full h-full">
<TeamSelector teams={teams} />
<Switch>
<Route exact path="/">
<section className="m-12 text-xl">
<h3>Please select a team</h3>
</section>
</Route>
<Route exact path="/team">
<section className="m-12 text-xl">
<h3>Please select a team</h3>
</section>
</Route>
<Route
path="/team/:teamId"
children={({ match }: { match: match<{ teamId: string }> }) => (
<SelectedTeam match={match} teams={teams} />
)}
/>
</Switch>
</div>
</Router>
);
}
Example #7
Source File: Commits.tsx From amplication with Apache License 2.0 | 6 votes |
function Entities({ match }: Props) {
const { application } = match.params;
useNavigationTabs(application, NAVIGATION_KEY, match.url, "Commits");
return (
<Switch>
<RouteWithAnalytics
exact
path="/:application/commits/"
component={CommitList}
/>
<RouteWithAnalytics
path="/:application/commits/:commitId"
component={CommitPage}
/>
</Switch>
);
}
Example #8
Source File: RolesPage.tsx From amplication with Apache License 2.0 | 6 votes |
RolesPage = ({ match }: Props) => {
const { application } = match.params;
useNavigationTabs(application, NAVIGATION_KEY, match.url, "Roles");
const roleMatch = useRouteMatch<{ roleId: string }>(
"/:application/roles/:roleId"
);
let roleId = null;
if (roleMatch) {
roleId = roleMatch.params.roleId;
}
return (
<PageContent
className="roles"
sideContent={
<RoleList applicationId={application} selectFirst={null === roleId} />
}
>
{!isEmpty(roleId) && <Role />}
</PageContent>
);
}
Example #9
Source File: Entities.tsx From amplication with Apache License 2.0 | 6 votes |
function Entities({ match }: Props) {
return (
<Switch>
<RouteWithAnalytics
exact
path="/:application/entities/"
component={EntityList}
/>
<Route path="/:application/entities/:entityId" component={Entity} />
</Switch>
);
}
Example #10
Source File: SyncWithGithubPage.tsx From amplication with Apache License 2.0 | 6 votes |
function SyncWithGithubPage({ match }: Props) {
const { application } = match.params;
const { data, error, refetch } = useQuery<{ app: AppWithGitRepository }>(
GET_APP_GIT_REPOSITORY,
{
variables: {
appId: application,
},
}
);
useNavigationTabs(application, NAVIGATION_KEY, match.url, `GitHub`);
const errorMessage = formatError(error);
return (
<PageContent>
<div className={CLASS_NAME}>
<div className={`${CLASS_NAME}__header`}>
<Icon icon="github" size="xlarge" />
<h1>Sync with GitHub</h1>
</div>
<div className={`${CLASS_NAME}__message`}>
Enable sync with GitHub to automatically push the generated code of
your application and create a Pull Request in your GitHub repository
every time you commit your changes.
</div>
{data?.app && <AuthAppWithGit app={data.app} onDone={refetch} />}
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
</PageContent>
);
}
Example #11
Source File: WorkspaceLayout.tsx From amplication with Apache License 2.0 | 5 votes |
function WorkspaceLayout({ match }: Props) {
if (isMobileOnly) {
return <MobileMessage />;
}
return (
<MainLayout className={CLASS_NAME}>
<MainLayout.Menu>
<MenuItemWithFixedPanel
tooltip=""
icon={false}
isOpen
panelKey={"panelKey"}
onClick={() => {}}
>
<WorkspaceSelector />
<div className={`${CLASS_NAME}__tabs`}>
<InnerTabLink to={`/`} icon="grid">
Apps
</InnerTabLink>
<InnerTabLink to={`/workspace/settings`} icon="settings">
Workspace Settings
</InnerTabLink>
<InnerTabLink to={`/workspace/members`} icon="users">
Workspace Members
</InnerTabLink>
{/* <InnerTabLink to={`/workspace/plans`} icon="file_text">
Workspace Plan
</InnerTabLink> */}
</div>
</MenuItemWithFixedPanel>
</MainLayout.Menu>
<MainLayout.Content>
<CompleteInvitation />
<div className={`${CLASS_NAME}__app-container`}>
<PageContent className={CLASS_NAME}>
<Switch>
<RouteWithAnalytics exact path="/workspace/settings">
<WorkspaceForm />
</RouteWithAnalytics>
</Switch>
<Switch>
<RouteWithAnalytics
exact
path="/workspace/members"
component={MemberList}
/>
</Switch>
{/* <Switch>
<RouteWithAnalytics exact path="/workspace/plans" component={Subscription} />
</Switch> */}
<Switch>
<RouteWithAnalytics exact path="/user/profile">
<ProfilePage />
</RouteWithAnalytics>
</Switch>
<Switch>
<RouteWithAnalytics exact path="/">
<ApplicationList />
</RouteWithAnalytics>
</Switch>
</PageContent>
</div>
</MainLayout.Content>
<ScreenResolutionMessage />
</MainLayout>
);
}
Example #12
Source File: index.tsx From metaflow-ui with Apache License 2.0 | 5 votes |
/**
* Find need for various buttons in breadcrumb. This is now very attached to fixed urls we have now
* so we might need to make this more generic later.
* @param routeMatch
* @param location
*/
export function findAdditionalButtons(routeMatch: match<KnownURLParams> | null, location: string): BreadcrumbButtons[] {
if (routeMatch === null) return [];
const queryParams = new URLSearchParams(location);
const buttons = [];
const params = routeMatch.params;
const flowValue = queryParams.get('flow_id') || params.flowId;
if (flowValue && flowValue.split(',').length === 1) {
buttons.push({
label: `${flowValue}`,
path: getPath.home() + '?flow_id=' + flowValue,
});
}
if (params.flowId && params.runNumber) {
buttons.push({
label: `${params.runNumber}`,
path: getPath.timeline(params.flowId, params.runNumber),
});
}
// Special case since step name might be found from route params or query params.
const stepValue = queryParams.get('steps') || params.stepName;
if (params.flowId && params.runNumber && stepValue) {
buttons.push({
label: stepValue,
path: getPath.step(params.flowId, params.runNumber, stepValue || 'undefined'),
});
}
if (params.flowId && params.runNumber && params.stepName && params.taskId) {
buttons.push({
label: params.taskId,
path: getPath.task(params.flowId, params.runNumber, params.stepName, params.taskId),
});
}
return buttons;
}
Example #13
Source File: root.component.test.tsx From openmrs-esm-patient-registration with MIT License | 5 votes |
sampleMatchProp: match<{ patientUuid: string }> = {
isExact: false,
path,
url: path.replace(':patientUuid', '1'),
params: { patientUuid: '1' },
}
Example #14
Source File: patient-registration.test.tsx From openmrs-esm-patient-registration with MIT License | 5 votes |
sampleMatchProp: match<{ patientUuid: string }> = {
isExact: false,
path,
url: path.replace(':patientUuid', '1'),
params: { patientUuid: '1' },
}
Example #15
Source File: PendingChangesPage.tsx From amplication with Apache License 2.0 | 5 votes |
PendingChangesPage = ({ match }: Props) => {
const { application } = match.params;
const [splitView, setSplitView] = useState<boolean>(false);
useNavigationTabs(application, NAVIGATION_KEY, match.url, "Pending Changes");
const handleChangeType = useCallback(
(type: string) => {
setSplitView(type === SPLIT);
},
[setSplitView]
);
const { data, error } = useQuery<TData>(GET_PENDING_CHANGES, {
variables: {
applicationId: application,
},
});
const errorMessage = formatError(error);
return (
<>
<PageContent className={CLASS_NAME}>
{!data ? (
"loading..."
) : (
<div className={`${CLASS_NAME}__header`}>
<h1>Pending Changes</h1>
<MultiStateToggle
label=""
name="compareMode"
options={OPTIONS}
onChange={handleChangeType}
selectedValue={splitView ? SPLIT : UNIFIED}
/>
</div>
)}
<div className={`${CLASS_NAME}__changes`}>
{data?.pendingChanges.map((change) => (
<PendingChangeWithCompare
key={change.resourceId}
change={change}
compareType={EnumCompareType.Pending}
splitView={splitView}
/>
))}
</div>
</PageContent>
<Snackbar open={Boolean(error)} message={errorMessage} />
</>
);
}
Example #16
Source File: CommitList.tsx From amplication with Apache License 2.0 | 5 votes |
CommitList = ({ match }: Props) => {
const { application } = match.params;
const [searchPhrase, setSearchPhrase] = useState<string>("");
const handleSearchChange = useCallback(
(value) => {
setSearchPhrase(value);
},
[setSearchPhrase]
);
const { data, loading, error, refetch, stopPolling, startPolling } = useQuery<
TData
>(GET_COMMITS, {
variables: {
appId: application,
orderBy: {
[CREATED_AT_FIELD]: models.SortOrder.Desc,
},
whereMessage:
searchPhrase !== ""
? { contains: searchPhrase, mode: models.QueryMode.Insensitive }
: undefined,
},
});
//start polling with cleanup
useEffect(() => {
refetch().catch(console.error);
startPolling(POLL_INTERVAL);
return () => {
stopPolling();
};
}, [refetch, stopPolling, startPolling]);
const errorMessage = formatError(error);
return (
<PageContent className={CLASS_NAME}>
<div className={`${CLASS_NAME}__header`}>
<SearchField
label="search"
placeholder="search"
onChange={handleSearchChange}
/>
</div>
<div className={`${CLASS_NAME}__title`}>
{data?.commits?.length} Commits
</div>
{loading && <CircularProgress />}
{data?.commits.map((commit) => (
<CommitListItem
key={commit.id}
commit={commit}
applicationId={application}
/>
))}
<Snackbar open={Boolean(error)} message={errorMessage} />
</PageContent>
);
}
Example #17
Source File: ApplicationLayout.tsx From amplication with Apache License 2.0 | 5 votes |
enhance = track((props) => {
return { applicationId: props.match.params.application };
})
Example #18
Source File: Entity.tsx From amplication with Apache License 2.0 | 5 votes |
enhance = track((props) => {
return { entityId: props.match.params.entityId };
})
Example #19
Source File: BuildPage.tsx From amplication with Apache License 2.0 | 4 votes |
BuildPage = ({ match }: Props) => {
const { application, buildId } = match.params;
const truncatedId = useMemo(() => {
return truncateId(buildId);
}, [buildId]);
useNavigationTabs(
application,
`${NAVIGATION_KEY}_${buildId}`,
match.url,
`Build ${truncatedId}`
);
const [error, setError] = useState<Error>();
const [getCommit, { data: commitData }] = useLazyQuery<{
commit: models.Commit;
}>(GET_COMMIT);
const { data, error: errorLoading } = useQuery<{
build: models.Build;
}>(GET_BUILD, {
variables: {
buildId: buildId,
},
onCompleted: (data) => {
getCommit({ variables: { commitId: data.build.commitId } });
},
});
const actionLog = useMemo<LogData | null>(() => {
if (!data?.build) return null;
if (!data.build.action) return null;
return {
action: data.build.action,
title: "Build log",
versionNumber: data.build.version,
};
}, [data]);
const errorMessage =
formatError(errorLoading) || (error && formatError(error));
return (
<>
<PageContent className={CLASS_NAME}>
{!data ? (
"loading..."
) : (
<>
<div className={`${CLASS_NAME}__header`}>
<h2>
Build <TruncatedId id={data.build.id} />
</h2>
{commitData && (
<ClickableId
label="Commit"
to={`/${application}/commits/${commitData.commit.id}`}
id={commitData.commit.id}
eventData={{
eventName: "commitHeaderIdClick",
}}
/>
)}
</div>
<div className={`${CLASS_NAME}__build-details`}>
<BuildSteps build={data.build} onError={setError} />
<aside className="log-container">
<ActionLog
action={actionLog?.action}
title={actionLog?.title || ""}
versionNumber={actionLog?.versionNumber || ""}
/>
</aside>
</div>
</>
)}
</PageContent>
<Snackbar open={Boolean(error || errorLoading)} message={errorMessage} />
</>
);
}
Example #20
Source File: CommitPage.tsx From amplication with Apache License 2.0 | 4 votes |
CommitPage = ({ match }: Props) => {
const { application, commitId } = match.params;
const [splitView, setSplitView] = useState<boolean>(false);
const handleChangeType = useCallback(
(type: string) => {
setSplitView(type === SPLIT);
},
[setSplitView]
);
const truncatedId = useMemo(() => {
return truncateId(commitId);
}, [commitId]);
useNavigationTabs(
application,
`${NAVIGATION_KEY}_${commitId}`,
match.url,
`Commit ${truncatedId}`
);
const { data, error } = useQuery<{
commit: models.Commit;
}>(GET_COMMIT, {
variables: {
commitId: commitId,
},
});
const build =
(data?.commit?.builds &&
data?.commit?.builds.length &&
data.commit.builds[0]) ||
null;
const errorMessage = formatError(error);
return (
<>
<PageContent className={CLASS_NAME}>
{!data ? (
"loading..."
) : (
<>
<div className={`${CLASS_NAME}__header`}>
<h2>
Commit <TruncatedId id={data.commit.id} />
</h2>
<UserAndTime
account={data.commit.user?.account}
time={data.commit.createdAt}
/>
<span className="spacer" />
{build && (
<ClickableId
label="Build"
to={`/${application}/builds/${build.id}`}
id={build.id}
eventData={{
eventName: "buildHeaderIdClick",
}}
/>
)}
</div>
<div className={`${CLASS_NAME}__commit-message`}>
{data.commit.message}
</div>
</>
)}
{data?.commit?.changes && (
<div className={`${CLASS_NAME}__changes`}>
<div className={`${CLASS_NAME}__changes__title`}>
<h3 className={`${CLASS_NAME}__changes__count`}>
{data.commit.changes.length}
{data.commit.changes.length > 1 ? " changes" : " change"}
</h3>
<MultiStateToggle
label=""
name="compareMode"
options={OPTIONS}
onChange={handleChangeType}
selectedValue={splitView ? SPLIT : UNIFIED}
/>
</div>
{data.commit.changes.map((change) => (
<PendingChangeWithCompare
key={change.resourceId}
change={change}
compareType={EnumCompareType.Previous}
splitView={splitView}
/>
))}
</div>
)}
</PageContent>
<Snackbar open={Boolean(error)} message={errorMessage} />
</>
);
}
Example #21
Source File: ApplicationLayout.tsx From amplication with Apache License 2.0 | 4 votes |
function ApplicationLayout({ match }: Props) {
const { application } = match.params;
const [pendingChanges, setPendingChanges] = useState<PendingChangeItem[]>([]);
const [commitRunning, setCommitRunning] = useState<boolean>(false);
const [isError, setIsError] = useState<boolean>(false);
const { data: pendingChangesData, refetch } = useQuery<
PendingChangeStatusData
>(GET_PENDING_CHANGES_STATUS, {
variables: {
applicationId: application,
},
});
const { data: applicationData } = useQuery<ApplicationData>(GET_APPLICATION, {
variables: {
id: match.params.application,
},
});
useEffect(() => {
setPendingChanges(
pendingChangesData ? pendingChangesData.pendingChanges : []
);
}, [pendingChangesData, setPendingChanges]);
const addChange = useCallback(
(
resourceId: string,
resourceType: models.EnumPendingChangeResourceType
) => {
const existingChange = pendingChanges.find(
(changeItem) =>
changeItem.resourceId === resourceId &&
changeItem.resourceType === resourceType
);
if (existingChange) {
//reassign pending changes to trigger refresh
setPendingChanges([...pendingChanges]);
} else {
setPendingChanges(
pendingChanges.concat([
{
resourceId,
resourceType,
},
])
);
}
},
[pendingChanges, setPendingChanges]
);
const addEntity = useCallback(
(entityId: string) => {
addChange(entityId, models.EnumPendingChangeResourceType.Entity);
},
[addChange]
);
const addBlock = useCallback(
(blockId: string) => {
addChange(blockId, models.EnumPendingChangeResourceType.Block);
},
[addChange]
);
const resetPendingChanges = useCallback(() => {
setPendingChanges([]);
refetch();
}, [refetch]);
const setCommitRunningCallback = useCallback(
(isRunning: boolean) => {
setCommitRunning(isRunning);
},
[setCommitRunning]
);
const setIsErrorCallback = useCallback(
(onError: boolean) => {
setIsError(onError);
},
[setIsError]
);
const pendingChangesContextValue = useMemo(
() => ({
pendingChanges,
commitRunning,
isError,
setIsError: setIsErrorCallback,
setCommitRunning: setCommitRunningCallback,
addEntity,
addBlock,
addChange,
reset: resetPendingChanges,
}),
[
pendingChanges,
commitRunning,
isError,
addEntity,
addBlock,
addChange,
resetPendingChanges,
setCommitRunningCallback,
setIsErrorCallback,
]
);
return (
<PendingChangesContext.Provider value={pendingChangesContextValue}>
<MainLayout
className={CLASS_NAME}
footer={<LastCommit applicationId={application} />}
>
<MainLayout.Menu>
<MenuItem
className={`${CLASS_NAME}__app-icon`}
title="Dashboard"
to={`/${application}`}
>
<CircleBadge
name={applicationData?.app.name || ""}
color={applicationData?.app.color}
/>
</MenuItem>
<MenuItem
title="Entities"
to={`/${application}/entities`}
icon="entity_outline"
/>
<MenuItem
title="Roles"
to={`/${application}/roles`}
icon="roles_outline"
/>
<MenuItem
title="Commits"
to={`/${application}/commits`}
icon="history_commit_outline"
/>
<MenuItem
title="Connect to GitHub"
to={`/${application}/github`}
icon="github"
/>
</MainLayout.Menu>
<MainLayout.Content>
<div className={`${CLASS_NAME}__app-container`}>
<NavigationTabs defaultTabUrl={`/${application}/`} />
<Switch>
<RouteWithAnalytics
path="/:application/pending-changes"
component={PendingChangesPage}
/>
<Route path="/:application/entities/" component={Entities} />
<RouteWithAnalytics
path="/:application/builds/:buildId"
component={BuildPage}
/>
<RouteWithAnalytics
path="/:application/roles"
component={RolesPage}
/>
<Route path="/:application/commits" component={Commits} />
<RouteWithAnalytics
path="/:application/fix-related-entities"
component={RelatedFieldsMigrationFix}
/>
<RouteWithAnalytics
path="/:application/github"
component={SyncWithGithubPage}
/>
<Route path="/:application/" component={ApplicationHome} />
</Switch>
</div>
</MainLayout.Content>
<MainLayout.Aside>
<AsidePanel.Target className="main-layout__aside__expandable" />
</MainLayout.Aside>
<ScreenResolutionMessage />
</MainLayout>
</PendingChangesContext.Provider>
);
}
Example #22
Source File: RelatedFieldsMigrationFix.tsx From amplication with Apache License 2.0 | 4 votes |
RelatedFieldsMigrationFix = ({ match }: Props) => {
const applicationId = match.params.application;
const pendingChangesContext = useContext(PendingChangesContext);
useNavigationTabs(
applicationId,
NAVIGATION_KEY,
match.url,
"Fix Entity Relations"
);
const { data, loading, error, refetch } = useQuery<TData>(GET_LOOKUP_FIELDS, {
variables: {
appId: applicationId,
},
});
const [createDefaultRelatedEntity, { error: createError }] = useMutation<{
createDefaultRelatedField: models.EntityField;
}>(CREATE_DEFAULT_RELATED_ENTITY, {
onCompleted: (createData) => {
refetch();
pendingChangesContext.addEntity(
createData.createDefaultRelatedField.properties.relatedEntityId
);
const entity = data?.app.entities.find((entity) =>
entity.fields?.some(
(field) => field.id === createData.createDefaultRelatedField.id
)
);
if (entity) {
pendingChangesContext.addEntity(entity.id);
}
},
});
const handleRelatedFieldFormSubmit = useCallback(
(relatedFieldValues: FormValues) => {
createDefaultRelatedEntity({
variables: {
fieldId: relatedFieldValues.fieldId,
relatedFieldDisplayName: relatedFieldValues.relatedFieldDisplayName,
relatedFieldName: camelCase(
relatedFieldValues.relatedFieldDisplayName
),
},
}).catch(console.error);
},
[createDefaultRelatedEntity]
);
const entityDictionary = useMemo(() => {
return keyBy(data?.app.entities, (entity) => entity.id);
}, [data]);
const fieldDictionary = useMemo(() => {
const allFields =
data?.app.entities.flatMap((entity) => entity.fields || []) || [];
const d = keyBy(allFields, (field) => field.permanentId);
console.log(d);
return d;
}, [data]);
const errorMessage =
(error && formatError(error)) || (createError && formatError(createError));
return (
<PageContent className={CLASS_NAME}>
<h2>New Release Updates</h2>
<div className={`${CLASS_NAME}__message`}>
Version 0.3.2 includes big improvements in how we manage related
entities. The changes require your attention. <br />
Following is a list of all the entities in your app, please provide the
missing names for each of your existing relation fields.
<span className={`${CLASS_NAME}__highlight`}>
{" "}
It will only take you a minute!
</span>
</div>
{loading && <CircularProgress />}
{data?.app.entities?.map((entity) => (
<Panel className={`${CLASS_NAME}__entity`} key={entity.id}>
<PanelHeader>{entity.displayName}</PanelHeader>
<div className={`${CLASS_NAME}__entity__fields`}>
{entity.fields && entity.fields.length
? entity.fields?.map((field) => (
<EntityRelationFieldsChart
key={field.id}
fixInPlace
applicationId={applicationId}
entityId={entity.id}
entityName={entity.displayName}
field={field}
relatedField={
fieldDictionary[field.properties.relatedFieldId]
}
relatedEntityName={
entityDictionary[field.properties.relatedEntityId]
.displayName
}
onSubmit={handleRelatedFieldFormSubmit}
/>
))
: "No relation fields"}
</div>
</Panel>
))}
<Snackbar
open={Boolean(error) || Boolean(createError)}
message={errorMessage}
/>
</PageContent>
);
}
Example #23
Source File: ApplicationHome.tsx From amplication with Apache License 2.0 | 4 votes |
function ApplicationHome({ match }: Props) {
const applicationId = match.params.application;
const location = useLocation();
const { data, error } = useQuery<{
app: models.App;
}>(GET_APPLICATION, {
variables: {
id: applicationId,
},
});
useNavigationTabs(
applicationId,
NAVIGATION_KEY,
location.pathname,
data?.app.name
);
const errorMessage = formatError(error);
return (
<PageContent
className={CLASS_NAME}
sideContent={
<div>
<div>
<InnerTabLink to={`/${applicationId}/`} icon="home">
Overview
</InnerTabLink>
</div>
<div>
<InnerTabLink to={`/${applicationId}/update`} icon="settings">
App Settings
</InnerTabLink>
</div>
<div>
<InnerTabLink to={`/${applicationId}/db/update`} icon="settings">
DB Settings
</InnerTabLink>
</div>
<div>
<InnerTabLink to={`/${applicationId}/auth/update`} icon="settings">
Auth Settings
</InnerTabLink>
</div>
<div>
<InnerTabLink to={`/${applicationId}/api-tokens`} icon="id">
API Tokens
</InnerTabLink>
</div>
</div>
}
>
<Switch>
<RouteWithAnalytics
path="/:application/api-tokens"
component={ApiTokenList}
/>
<Route
path="/:application/"
render={() => (
<>
<div
className={classNames(
`${CLASS_NAME}__header`,
`theme-${data && COLOR_TO_NAME[data.app.color]}`
)}
>
{data?.app.name}
<CircleBadge
name={data?.app.name || ""}
color={data?.app.color || "transparent"}
/>
</div>
<Switch>
<RouteWithAnalytics
exact
path="/:application/"
component={() => (
<div className={`${CLASS_NAME}__tiles`}>
<NewVersionTile applicationId={applicationId} />
<EntitiesTile applicationId={applicationId} />
<RolesTile applicationId={applicationId} />
<SyncWithGithubTile applicationId={applicationId} />
</div>
)}
/>
<RouteWithAnalytics
path="/:application/update"
component={ApplicationForm}
/>
<RouteWithAnalytics
path="/:application/db/update"
component={ApplicationDatabaseSettingsForms}
/>
<RouteWithAnalytics
path="/:application/auth/update"
component={ApplicationAuthSettingForm}
/>
</Switch>
</>
)}
/>
</Switch>
<Snackbar open={Boolean(error)} message={errorMessage} />
</PageContent>
);
}
Example #24
Source File: ApplicationForm.tsx From amplication with Apache License 2.0 | 4 votes |
function ApplicationForm({ match }: Props) {
const applicationId = match.params.application;
const { data, error } = useQuery<{
app: models.App;
}>(GET_APPLICATION, {
variables: {
id: applicationId,
},
});
const { trackEvent } = useTracking();
const [updateApp, { error: updateError }] = useMutation<TData>(UPDATE_APP);
const handleSubmit = useCallback(
(data) => {
const { name, description, color } = data;
trackEvent({
eventName: "updateAppInfo",
});
updateApp({
variables: {
data: {
name,
description,
color,
},
appId: applicationId,
},
}).catch(console.error);
},
[updateApp, applicationId, trackEvent]
);
const handleColorChange = useCallback(
(color: string) => {
trackEvent({
eventName: "updateAppColor",
});
updateApp({
variables: {
data: {
color,
},
appId: applicationId,
},
}).catch(console.error);
},
[updateApp, applicationId, trackEvent]
);
const errorMessage = formatError(error || updateError);
return (
<div className={CLASS_NAME}>
{data?.app && (
<>
<Formik
initialValues={data.app}
validate={(values: models.App) => validate(values, FORM_SCHEMA)}
enableReinitialize
onSubmit={handleSubmit}
>
{(formik) => {
return (
<Form>
<h3>App Settings</h3>
<FormikAutoSave debounceMS={1000} />
<TextField name="name" label="Name" />
<TextField
autoComplete="off"
textarea
rows={3}
name="description"
label="Description"
/>
</Form>
);
}}
</Formik>
<div>
<hr />
<h3>
<Icon icon="color" />
App Color
</h3>
{COLORS.map((color) => (
<ColorSelectButton
color={color}
key={color.value}
onColorSelected={handleColorChange}
/>
))}
</div>
</>
)}
<Snackbar open={Boolean(error?.message || updateError?.message)} message={errorMessage} />
</div>
);
}
Example #25
Source File: Character.tsx From client with MIT License | 4 votes |
Character: React.FC<Props> = ({
match: {
params: { name }
}
}) => {
const [inv, setInv] = useState<any>();
const { loading, char } = useSelector(
(state: AppState) => state.rankings.character
);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getCharacter(name));
return () => {
dispatch(clearCharacter());
};
}, [dispatch, name]);
useEffect(() => {
char && setInv(inventory.decode(char.Inventory));
}, [char]);
return (
<div className='Character'>
{loading ? (
<Loader />
) : !char ? (
`This character doesn't exist`
) : (
<>
<table className='char-info'>
<tbody>
<tr>
<td colSpan={2}>
<Name char={char} style={{ display: 'inline-block' }} />
</td>
</tr>
<tr>
<td className='image'>
<img
src={`/images/classes/${cclass.shortClass(char.Class)}.jpg`}
alt='char'
/>
</td>
<td className='info'>
<table>
<tbody>
<tr>
<td style={{ width: '50%' }}>Class</td>
<td>{cclass.charClass(char.Class)}</td>
</tr>
<tr>
<td>Level</td>
<td>
{char.cLevel}
<sup>{char.Resets}</sup>
</td>
</tr>
<tr>
<td>Total Points</td>
<td>{char.totalPoints.toLocaleString()}</td>
</tr>
<tr>
<td>Status</td>
<td
dangerouslySetInnerHTML={{
__html: rankings.pkStatus(char.PkCount)
}}
></td>
</tr>
<tr>
<td>HOF Wins</td>
<td>{char.HOFWins}</td>
</tr>
<tr>
<td>Location</td>
<td>
<span
dangerouslySetInnerHTML={{
__html: rankings.location(char.MapNumber)
}}
/>{' '}
( {char.MapPosX}, {char.MapPosY} )
</td>
</tr>
<tr>
<td>Zen</td>
<td>{char.Money.toLocaleString()}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<div className='equipment'>
<div className='title'>Equipment</div>
<div className='container'>
<div
className='content'
style={{
backgroundImage: `url('/images/classes/${cclass.shortClass(
char.Class
)}_inv.png')`
}}
>
{inv &&
Object.keys(inv).map((key, i) => (
<div key={i} className={`item ${key}`}>
{inv[key] && (
<Item
hex={inv[key]}
style={{ maxWidth: '100%', maxHeight: '100%' }}
/>
)}
</div>
))}
</div>
</div>
</div>
</>
)}
</div>
);
}
Example #26
Source File: Guild.tsx From client with MIT License | 4 votes |
Guild: React.FC<Props> = ({
match: {
params: { name }
}
}) => {
const [master, setMaster] = useState<Character>();
const [resetPoints, setResetPoints] = useState(0);
const [alliance, setAlliance] = useState<IGuild[]>();
const { loading, data: guild } = useSelector(
(state: AppState) => state.rankings.guild
);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getGuild(name));
return () => {
dispatch(clearGuild());
};
}, [dispatch, name]);
useEffect(() => {
if (guild) {
let rPoints = 0;
guild.members.forEach(m => {
rPoints += m.character.Resets;
});
const allys = guild.alliance.filter(
g => g.G_Name !== guild.G_Name && g.G_Union !== 0
);
setMaster(guild.members.find(m => m.Name === guild.G_Master)?.character);
setResetPoints(rPoints);
setAlliance(allys);
}
}, [guild]);
return (
<div className='Guild'>
{loading ? (
<Loader />
) : !guild ? (
`This guild doesn't exist`
) : (
<>
<table className='guild-info'>
<tbody>
<tr>
<td colSpan={2} style={{ color: '#eeeeee' }}>
{guild.G_Name}
</td>
</tr>
<tr>
<td className='image'>
<Mark mark={guild.G_Mark} size={100} />
</td>
<td className='info'>
<table>
<tbody>
<tr>
<td style={{ width: '50%' }}>Guild Master</td>
<td>
{master && <Name char={master} guild={false} />}
</td>
</tr>
<tr>
<td>Alliance</td>
<td>
{alliance && alliance.length
? alliance.map((g, i) => {
return (
<span key={i}>
<Link to={`/guild/${g.G_Name}`}>
{g.G_Name}
</Link>
{i + 1 !== alliance.length ? ', ' : ''}
</span>
);
})
: '-'}
</td>
</tr>
<tr>
<td>Reset Points</td>
<td>{resetPoints}</td>
</tr>
<tr>
<td>Guild Score</td>
<td>{guild.G_Score}</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<div className='equipment'>
<div className='title'>Members ( {guild.members.length} )</div>
<div className='container'>
<table className='Table'>
<thead>
<tr>
<th>#</th>
<th>name</th>
<th>
level <sup>res</sup>
</th>
<th>class</th>
<th>position</th>
</tr>
</thead>
<tbody>
{guild.members
.sort((a, b) => b.character.Resets - a.character.Resets)
.sort((a, b) => b.G_Status - a.G_Status)
.map((m, i) => (
<tr key={i}>
<td>{i + 1}</td>
<td>
<Name char={m.character} guild={false} />
</td>
<td>
{m.character.cLevel} <sup>{m.character.Resets}</sup>
</td>
<td>{cclass.charClass(m.character.Class)}</td>
<td
dangerouslySetInnerHTML={{
__html: rankings.guildPosition(m.G_Status)
}}
></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</>
)}
</div>
);
}
Example #27
Source File: Logs.tsx From client with MIT License | 4 votes |
Logs: React.FC<Props> = ({
match: {
params: { category }
}
}) => {
const [page, setPage] = useState(1);
const [perPage, setPerPage] = useState(20);
const {
loading,
logs: { list, count }
} = useSelector((state: AppState) => state.user.account);
const chars = useSelector((state: AppState) => state.user.character.list);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getLogs(page, perPage, category));
dispatch(getChars());
}, [dispatch, page, perPage, category]);
return (
<>
<div className='Logs'>
{loading ? (
<Loader />
) : list ? (
<table className='Table'>
<thead>
<tr>
<th>#</th>
<th>module</th>
<th>log</th>
<th>time</th>
<th>ip</th>
</tr>
</thead>
<tbody>
{list.map((log, i) => {
// Items
let message = reactStringReplace(
log.message,
/{item:([^}]{32})}/gim,
match => (
<Item
key={uuid()}
hex={match}
image={false}
style={{ display: 'inline-block' }}
/>
)
);
// Highlight of text
message = reactStringReplace(
message,
/{highlight:([^}]+)}/gm,
match => (
<span key={uuid()} className='highlight'>
{match}
</span>
)
);
// Character Names
message = reactStringReplace(
message,
/{char:([^}]+)}/gm,
match => {
const find = chars && chars.find(c => c.Name === match);
return (
<Name
key={uuid()}
char={{
Name: match,
status: find ? find.status : false
}}
guild={false}
style={{ display: 'inline-block' }}
/>
);
}
);
const module = log.module ? log.module : 'unknown';
return (
<tr key={i}>
<td>{i + 1 + (page - 1) * perPage}</td>
<td>
<Link to={`/user/account/logs/${module}`}>{module}</Link>
</td>
<td style={{ textAlign: 'left' }}>{message}</td>
<td>
<Moment
style={{
display: 'inline-block',
whiteSpace: 'nowrap'
}}
fromNow
unix
withTitle
>
{Math.floor(log.timestamp / 1000)}
</Moment>
</td>
<td style={{ whiteSpace: 'nowrap' }}>{log.ip}</td>
</tr>
);
})}
</tbody>
</table>
) : (
<div className='NoData'>No logs</div>
)}
</div>
<Pagination
page={page}
perPage={perPage}
totalItems={count || 0}
setPage={setPage}
setPerPage={setPerPage}
/>
</>
);
}
Example #28
Source File: EntityList.tsx From amplication with Apache License 2.0 | 4 votes |
EntityList = ({ match }: Props) => {
const { application } = match.params;
const [error, setError] = useState<Error>();
useNavigationTabs(application, NAVIGATION_KEY, match.url, "Entities");
const [searchPhrase, setSearchPhrase] = useState<string>("");
const [newEntity, setNewEntity] = useState<boolean>(false);
const handleNewEntityClick = useCallback(() => {
setNewEntity(!newEntity);
}, [newEntity, setNewEntity]);
const {
data,
loading,
error: errorLoading,
refetch,
stopPolling,
startPolling,
} = useQuery<TData>(GET_ENTITIES, {
variables: {
id: application,
orderBy: {
[NAME_FIELD]: models.SortOrder.Asc,
},
whereName:
searchPhrase !== ""
? { contains: searchPhrase, mode: models.QueryMode.Insensitive }
: undefined,
},
});
const handleSearchChange = useCallback(
(value) => {
setSearchPhrase(value);
},
[setSearchPhrase]
);
//start polling with cleanup
useEffect(() => {
refetch().catch(console.error);
startPolling(POLL_INTERVAL);
return () => {
stopPolling();
};
}, [refetch, stopPolling, startPolling]);
const errorMessage =
formatError(errorLoading) || (error && formatError(error));
return (
<PageContent className={CLASS_NAME}>
<Dialog
className="new-entity-dialog"
isOpen={newEntity}
onDismiss={handleNewEntityClick}
title="New Entity"
>
<NewEntity applicationId={application} />
</Dialog>
<div className={`${CLASS_NAME}__header`}>
<SearchField
label="search"
placeholder="search"
onChange={handleSearchChange}
/>
<Button
className={`${CLASS_NAME}__add-button`}
buttonStyle={EnumButtonStyle.Primary}
onClick={handleNewEntityClick}
icon="plus"
>
Add entity
</Button>
</div>
<div className={`${CLASS_NAME}__title`}>
{data?.entities.length} Entities
</div>
{loading && <CircularProgress />}
{data?.entities.map((entity) => (
<EntityListItem
key={entity.id}
entity={entity}
applicationId={application}
onError={setError}
/>
))}
<Snackbar open={Boolean(error || errorLoading)} message={errorMessage} />
</PageContent>
);
/**@todo: move error message to hosting page */
}
Example #29
Source File: ApplicationDatabaseSettingsForms.tsx From amplication with Apache License 2.0 | 4 votes |
function ApplicationDatabaseSettingsForms({ match }: Props) {
const applicationId = match.params.application;
const { data, error } = useQuery<{
appSettings: models.AppSettings;
}>(GET_APP_SETTINGS, {
variables: {
id: applicationId,
},
});
const pendingChangesContext = useContext(PendingChangesContext);
const { trackEvent } = useTracking();
const [updateAppSettings, { error: updateError }] = useMutation<TData>(
UPDATE_APP_SETTINGS,
{
onCompleted: (data) => {
pendingChangesContext.addBlock(data.updateAppSettings.id);
},
}
);
const handleSubmit = useCallback(
(data: models.AppSettings) => {
const { dbHost, dbName, dbPassword, dbPort, dbUser, authProvider } = data;
trackEvent({
eventName: "updateAppSettings",
});
updateAppSettings({
variables: {
data: {
dbHost,
dbName,
dbPassword,
dbPort,
dbUser,
authProvider,
},
appId: applicationId,
},
}).catch(console.error);
},
[updateAppSettings, applicationId, trackEvent]
);
const errorMessage = formatError(error || updateError);
return (
<div className={CLASS_NAME}>
{data?.appSettings && (
<Formik
initialValues={data.appSettings}
validate={(values: models.AppSettings) =>
validate(values, FORM_SCHEMA)
}
enableReinitialize
onSubmit={handleSubmit}
>
{(formik) => {
return (
<Form>
<h3>DB Settings</h3>
<p>
All the below settings will appear in clear text in the
generated app. <br />
It should only be used for the development environment
variables and should not include sensitive data.
</p>
<FormikAutoSave debounceMS={2000} />
<TextField name="dbHost" autoComplete="off" label="Host" />
<TextField
name="dbName"
autoComplete="off"
label="Database Name"
/>
<TextField
name="dbPort"
type="number"
autoComplete="off"
label="Port"
/>
<TextField name="dbUser" autoComplete="off" label="User" />
<TextField
name="dbPassword"
autoComplete="off"
label="Password"
/>
</Form>
);
}}
</Formik>
)}
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}