@apollo/client#Reference TypeScript Examples
The following examples show how to use
@apollo/client#Reference.
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: useDeleteBtnCallback.ts From jmix-frontend with Apache License 2.0 | 6 votes |
function defaultOnConfirm<
TEntity,
TData,
TVariables extends HasId = HasId
>(
entityInstance: EntityInstance<TEntity, HasId>,
executeDeleteMutation: GraphQLMutationFn<TData, TVariables>,
queryName: string
) {
return () => {
if (entityInstance.id != null) {
// noinspection JSIgnoredPromiseFromCall
executeDeleteMutation({
variables: { id: entityInstance.id } as TVariables,
update(cache: ApolloCache<TData>) {
// Remove deleted item from cache
cache.modify({
fields: {
[queryName](existingRefs, { readField }) {
return existingRefs.filter(
(ref: Reference) => entityInstance.id !== readField("id", ref)
);
}
}
});
}
});
}
};
}
Example #2
Source File: handleDuplicate.ts From lexicon with MIT License | 6 votes |
export function handleDuplicateRef<T extends Reference>(
firstArray: Array<T> | null,
secondArray: Array<T> | null,
): Array<T> {
if (!secondArray || !firstArray) {
return secondArray || firstArray || [];
}
const firstArrayIds = firstArray.map(({ __ref }) => __ref);
const filteredSecondArray = secondArray.filter(
(item) => !firstArrayIds.includes(item.__ref),
);
return [...firstArray, ...filteredSecondArray];
}
Example #3
Source File: DeleteEntityField.tsx From amplication with Apache License 2.0 | 4 votes |
DeleteEntityField = ({
entityField,
entityId,
showLabel = false,
onDelete,
onError,
}: Props) => {
const [confirmDelete, setConfirmDelete] = useState<boolean>(false);
const pendingChangesContext = useContext(PendingChangesContext);
const [deleteEntityField, { loading: deleteLoading }] = useMutation<DType>(
DELETE_ENTITY_FIELD,
{
update(cache, { data }) {
if (!data) return;
const deletedFieldId = data.deleteEntityField.id;
if (entityField.dataType === models.EnumDataType.Lookup) {
const relatedEntityId = entityField.properties.relatedEntityId;
cache.evict({
id: cache.identify({ id: relatedEntityId, __typename: "Entity" }),
});
}
cache.modify({
id: cache.identify({ id: entityId, __typename: "Entity" }),
fields: {
fields(existingFieldsRefs, { readField }) {
return existingFieldsRefs.filter(
(fieldRef: Reference) =>
deletedFieldId !== readField("id", fieldRef)
);
},
},
});
},
onCompleted: (data) => {
pendingChangesContext.addEntity(entityId);
onDelete && onDelete();
},
}
);
const handleDelete = useCallback(
(event) => {
event.stopPropagation();
setConfirmDelete(true);
},
[setConfirmDelete]
);
const handleDismissDelete = useCallback(() => {
setConfirmDelete(false);
}, [setConfirmDelete]);
const handleConfirmDelete = useCallback(() => {
setConfirmDelete(false);
deleteEntityField({
variables: {
entityFieldId: entityField.id,
},
}).catch(onError);
}, [entityField, deleteEntityField, onError]);
return (
<>
<ConfirmationDialog
isOpen={confirmDelete}
title={`Delete ${entityField.displayName}`}
confirmButton={CONFIRM_BUTTON}
dismissButton={DISMISS_BUTTON}
message="Are you sure you want to delete this entity field?"
onConfirm={handleConfirmDelete}
onDismiss={handleDismissDelete}
/>
<div className={CLASS_NAME}>
{!deleteLoading && !SYSTEM_DATA_TYPES.has(entityField.dataType) && (
<Button
buttonStyle={
showLabel ? EnumButtonStyle.Secondary : EnumButtonStyle.Clear
}
icon="trash_2"
onClick={handleDelete}
>
{showLabel && "Delete"}
</Button>
)}
</div>
</>
);
}
Example #4
Source File: EntityListItem.tsx From amplication with Apache License 2.0 | 4 votes |
EntityListItem = ({
entity,
applicationId,
onDelete,
onError,
}: Props) => {
const pendingChangesContext = useContext(PendingChangesContext);
const history = useHistory();
const [confirmDelete, setConfirmDelete] = useState<boolean>(false);
const [deleteEntity, { loading: deleteLoading }] = useMutation<DType>(
DELETE_ENTITY,
{
update(cache, { data }) {
if (!data) return;
const deletedEntityId = data.deleteEntity.id;
cache.modify({
fields: {
entities(existingEntityRefs, { readField }) {
return existingEntityRefs.filter(
(entityRef: Reference) =>
deletedEntityId !== readField("id", entityRef)
);
},
},
});
},
onCompleted: (data) => {
pendingChangesContext.addEntity(data.deleteEntity.id);
onDelete && onDelete();
},
}
);
const handleDelete = useCallback(
(event) => {
event.stopPropagation();
setConfirmDelete(true);
},
[setConfirmDelete]
);
const handleDismissDelete = useCallback(() => {
setConfirmDelete(false);
}, [setConfirmDelete]);
const handleConfirmDelete = useCallback(() => {
setConfirmDelete(false);
deleteEntity({
variables: {
entityId: entity.id,
},
}).catch(onError);
}, [entity, deleteEntity, onError]);
const handleRowClick = useCallback(() => {
history.push(`/${applicationId}/entities/${entity.id}`);
}, [history, applicationId, entity]);
const [latestVersion] = entity.versions;
return (
<>
<ConfirmationDialog
isOpen={confirmDelete}
title={`Delete ${entity.displayName}`}
confirmButton={CONFIRM_BUTTON}
dismissButton={DISMISS_BUTTON}
message="Are you sure you want to delete this entity?"
onConfirm={handleConfirmDelete}
onDismiss={handleDismissDelete}
/>
<Panel
className={CLASS_NAME}
clickable
onClick={handleRowClick}
panelStyle={EnumPanelStyle.Bordered}
>
<div className={`${CLASS_NAME}__row`}>
<Link
className={`${CLASS_NAME}__title`}
title={entity.displayName}
to={`/${applicationId}/entities/${entity.id}`}
>
{entity.displayName}
</Link>
{Boolean(entity.lockedByUser) && (
<LockStatusIcon lockedByUser={entity.lockedByUser} />
)}
<span className="spacer" />
{!deleteLoading && entity.name !== USER_ENTITY && (
<Button
buttonStyle={EnumButtonStyle.Clear}
icon="trash_2"
onClick={handleDelete}
/>
)}
</div>
<div className={`${CLASS_NAME}__row`}>
<span className={`${CLASS_NAME}__description`}>
{entity.description}
</span>
</div>
<div className={`${CLASS_NAME}__divider`} />
<div className={`${CLASS_NAME}__row`}>
<span className={`${CLASS_NAME}__label`}>Last commit:</span>
{latestVersion.commit && (
<UserAndTime
account={latestVersion.commit.user?.account}
time={latestVersion.commit.createdAt}
/>
)}
<span className={`${CLASS_NAME}__description`}>
{latestVersion.commit ? latestVersion.commit?.message : "Never"}
</span>
<span className="spacer" />
{entity.lockedByUser && (
<>
<span className={`${CLASS_NAME}__label`}>Locked by:</span>
<UserAndTime
account={entity.lockedByUser.account || {}}
time={entity.lockedAt}
/>
</>
)}
</div>
</Panel>
</>
);
}
Example #5
Source File: NewEntity.tsx From amplication with Apache License 2.0 | 4 votes |
NewEntity = ({ applicationId }: Props) => {
const { trackEvent } = useTracking();
const pendingChangesContext = useContext(PendingChangesContext);
const [createEntity, { error, data, loading }] = useMutation<DType>(
CREATE_ENTITY,
{
onCompleted: (data) => {
pendingChangesContext.addEntity(data.createOneEntity.id);
trackEvent({
eventName: "createEntity",
entityName: data.createOneEntity.displayName,
});
},
update(cache, { data }) {
if (!data) return;
const newEntity = data.createOneEntity;
cache.modify({
fields: {
entities(existingEntityRefs = [], { readField }) {
const newEntityRef = cache.writeFragment({
data: newEntity,
fragment: NEW_ENTITY_FRAGMENT,
});
if (
existingEntityRefs.some(
(EntityRef: Reference) =>
readField("id", EntityRef) === newEntity.id
)
) {
return existingEntityRefs;
}
return [...existingEntityRefs, newEntityRef];
},
},
});
},
}
);
const history = useHistory();
const handleSubmit = useCallback(
(data: CreateEntityType) => {
const displayName = data.displayName.trim();
const pluralDisplayName = generatePluralDisplayName(displayName);
const singularDisplayName = generateSingularDisplayName(displayName);
const name = pascalCase(singularDisplayName);
createEntity({
variables: {
data: {
...data,
displayName,
name,
pluralDisplayName,
app: { connect: { id: applicationId } },
},
},
}).catch(console.error);
},
[createEntity, applicationId]
);
useEffect(() => {
if (data) {
history.push(`/${applicationId}/entities/${data.createOneEntity.id}`);
}
}, [history, data, applicationId]);
const errorMessage = formatError(error);
return (
<div className={CLASS_NAME}>
<SvgThemeImage image={EnumImages.Entities} />
<div className={`${CLASS_NAME}__instructions`}>
Give your new entity a descriptive name. <br />
For example: Customer, Support Ticket, Purchase Order...
</div>
<Formik
initialValues={INITIAL_VALUES}
validate={(values: CreateEntityType) => validate(values, FORM_SCHEMA)}
onSubmit={handleSubmit}
validateOnMount
>
{(formik) => {
const handlers = {
SUBMIT: formik.submitForm,
};
return (
<Form>
<GlobalHotKeys keyMap={keyMap} handlers={handlers} />
<TextField
name="displayName"
label="New Entity Name"
disabled={loading}
autoFocus
hideLabel
placeholder="Type New Entity Name"
autoComplete="off"
/>
<Button
type="submit"
buttonStyle={EnumButtonStyle.Primary}
disabled={!formik.isValid || loading}
>
Create Entity
</Button>
</Form>
);
}}
</Formik>
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}
Example #6
Source File: NewEntityField.tsx From amplication with Apache License 2.0 | 4 votes |
NewEntityField = ({ entity, onFieldAdd }: Props) => {
const { trackEvent } = useTracking();
const pendingChangesContext = useContext(PendingChangesContext);
const inputRef = useRef<HTMLInputElement | null>(null);
const [autoFocus, setAutoFocus] = useState<boolean>(false);
const [createEntityField, { error, loading }] = useMutation<TData>(
CREATE_ENTITY_FIELD,
{
update(cache, { data }) {
if (!data) return;
const newEntityField = data.createEntityFieldByDisplayName;
if (newEntityField.dataType === models.EnumDataType.Lookup) {
const relatedEntityId = newEntityField.properties.relatedEntityId;
//remove the related entity from cache so it will be updated with the new relation field
cache.evict({
id: cache.identify({ id: relatedEntityId, __typename: "Entity" }),
});
}
cache.modify({
id: cache.identify(entity),
fields: {
fields(existingEntityFieldRefs = [], { readField }) {
const newEntityFieldRef = cache.writeFragment({
data: newEntityField,
fragment: NEW_ENTITY_FIELD_FRAGMENT,
});
if (
existingEntityFieldRefs.some(
(ref: Reference) => readField("id", ref) === newEntityField.id
)
) {
return existingEntityFieldRefs;
}
return [...existingEntityFieldRefs, newEntityFieldRef];
},
},
});
},
onCompleted: (data) => {
pendingChangesContext.addEntity(entity.id);
trackEvent({
eventName: "createEntityField",
entityFieldName: data.createEntityFieldByDisplayName.displayName,
dataType: data.createEntityFieldByDisplayName.dataType,
});
},
errorPolicy: "none",
}
);
const handleSubmit = useCallback(
(data, actions) => {
setAutoFocus(true);
createEntityField({
variables: {
data: {
displayName: data.displayName,
entity: { connect: { id: entity.id } },
},
},
})
.then((result) => {
if (onFieldAdd && result.data) {
onFieldAdd(result.data.createEntityFieldByDisplayName);
}
actions.resetForm();
inputRef.current?.focus();
})
.catch(console.error);
},
[createEntityField, entity.id, inputRef, onFieldAdd]
);
const errorMessage = formatError(error);
return (
<div className={CLASS_NAME}>
<Formik
initialValues={INITIAL_VALUES}
validateOnBlur={false}
onSubmit={handleSubmit}
>
{(formik) => (
<Form className={`${CLASS_NAME}__add-field`}>
<TextField
required
name="displayName"
label="New Field Name"
disabled={loading}
inputRef={inputRef}
placeholder="Add field"
autoComplete="off"
autoFocus={autoFocus}
hideLabel
className={`${CLASS_NAME}__add-field__text`}
/>
<Button
buttonStyle={EnumButtonStyle.Clear}
icon="plus"
className={classNames(`${CLASS_NAME}__add-field__button`, {
[`${CLASS_NAME}__add-field__button--show`]:
formik.values.displayName.length > 0,
})}
/>
</Form>
)}
</Formik>
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}
Example #7
Source File: NewRole.tsx From amplication with Apache License 2.0 | 4 votes |
NewRole = ({ onRoleAdd, applicationId }: Props) => {
const [createRole, { error, loading }] = useMutation(CREATE_ROLE, {
update(cache, { data }) {
if (!data) return;
const newAppRole = data.createAppRole;
cache.modify({
fields: {
appRoles(existingAppRoleRefs = [], { readField }) {
const newAppRoleRef = cache.writeFragment({
data: newAppRole,
fragment: NEW_ROLE_FRAGMENT,
});
if (
existingAppRoleRefs.some(
(appRoleRef: Reference) =>
readField("id", appRoleRef) === newAppRole.id
)
) {
return existingAppRoleRefs;
}
return [...existingAppRoleRefs, newAppRoleRef];
},
},
});
},
});
const inputRef = useRef<HTMLInputElement | null>(null);
const [autoFocus, setAutoFocus] = useState<boolean>(false);
const handleSubmit = useCallback(
(data, actions) => {
setAutoFocus(true);
createRole({
variables: {
data: {
...data,
name: camelCase(data.displayName),
app: { connect: { id: applicationId } },
},
},
})
.then((result) => {
if (onRoleAdd) {
onRoleAdd(result.data.createAppRole);
}
actions.resetForm();
inputRef.current?.focus();
})
.catch(console.error);
},
[createRole, applicationId, inputRef, onRoleAdd]
);
const errorMessage = formatError(error);
return (
<div className={CLASS_NAME}>
<Formik
initialValues={INITIAL_VALUES}
validate={(values: Partial<models.AppRole>) =>
validate(values, FORM_SCHEMA)
}
validateOnBlur={false}
onSubmit={handleSubmit}
>
{(formik) => (
<Form className={`${CLASS_NAME}__add-field`}>
<TextField
required
name="displayName"
label="New Role Name"
disabled={loading}
inputRef={inputRef}
placeholder="Add role"
autoComplete="off"
autoFocus={autoFocus}
hideLabel
className={`${CLASS_NAME}__add-field__text`}
/>
<Button
buttonStyle={EnumButtonStyle.Clear}
icon="plus"
className={classNames(`${CLASS_NAME}__add-field__button`, {
[`${CLASS_NAME}__add-field__button--show`]: !isEmpty(
formik.values.displayName
),
})}
/>
</Form>
)}
</Formik>
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}
Example #8
Source File: NewApiToken.tsx From amplication with Apache License 2.0 | 4 votes |
NewApiToken = ({ onCompleted }: Props) => {
const { trackEvent } = useTracking();
const [createApiToken, { error, loading }] = useMutation<DType>(
CREATE_API_TOKEN,
{
onCompleted: (data) => {
trackEvent({
eventName: "createApiToken",
tokenName: data.createApiToken.name,
});
onCompleted(data.createApiToken);
},
update(cache, { data }) {
if (!data) return;
const newToken = data.createApiToken;
cache.modify({
fields: {
userApiTokens(existingTokenRefs = [], { readField }) {
const newTokenRef = cache.writeFragment({
data: newToken,
fragment: NEW_API_TOKEN_FRAGMENT,
});
if (
existingTokenRefs.some(
(TokenRef: Reference) =>
readField("id", TokenRef) === newToken.id
)
) {
return existingTokenRefs;
}
return [newTokenRef, ...existingTokenRefs];
},
},
});
},
}
);
const handleSubmit = useCallback(
(data: models.ApiTokenCreateInput) => {
createApiToken({
variables: {
data,
},
}).catch(console.error);
},
[createApiToken]
);
const errorMessage = formatError(error);
return (
<div className={CLASS_NAME}>
<div className={`${CLASS_NAME}__instructions`}>
Give the new token a descriptive name.
</div>
<Formik
initialValues={INITIAL_VALUES}
validate={(values: models.ApiTokenCreateInput) =>
validate(values, FORM_SCHEMA)
}
onSubmit={handleSubmit}
validateOnMount
>
{(formik) => {
const handlers = {
SUBMIT: formik.submitForm,
};
return (
<Form>
<GlobalHotKeys keyMap={keyMap} handlers={handlers} />
<TextField
name="name"
label="Token Name"
disabled={loading}
autoFocus
hideLabel
placeholder="Token Name"
autoComplete="off"
/>
<Button
type="submit"
buttonStyle={EnumButtonStyle.Primary}
disabled={!formik.isValid || loading}
>
Create Token
</Button>
</Form>
);
}}
</Formik>
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}
Example #9
Source File: ApplicationList.tsx From amplication with Apache License 2.0 | 4 votes |
function ApplicationList() {
const { trackEvent } = useTracking();
const [searchPhrase, setSearchPhrase] = useState<string>("");
const [error, setError] = useState<Error | null>(null);
const clearError = useCallback(() => {
setError(null);
}, [setError]);
const [deleteApp] = useMutation<TDeleteData>(DELETE_APP, {
update(cache, { data }) {
if (!data) return;
const deletedAppId = data.deleteApp.id;
cache.modify({
fields: {
apps(existingAppRefs, { readField }) {
return existingAppRefs.filter(
(appRef: Reference) => deletedAppId !== readField("id", appRef)
);
},
},
});
},
});
const handleDelete = useCallback(
(app) => {
trackEvent({
eventName: "deleteApp",
});
deleteApp({
variables: {
appId: app.id,
},
}).catch(setError);
},
[deleteApp, setError, trackEvent]
);
const handleSearchChange = useCallback(
(value) => {
setSearchPhrase(value);
},
[setSearchPhrase]
);
const { data, error: errorLoading, loading } = useQuery<TData>(
GET_APPLICATIONS,
{
variables: {
whereName:
searchPhrase !== ""
? { contains: searchPhrase, mode: models.QueryMode.Insensitive }
: undefined,
},
}
);
const errorMessage =
formatError(errorLoading) || (error && formatError(error));
const handleNewAppClick = useCallback(() => {
trackEvent({
eventName: "createNewAppCardClick",
});
}, [trackEvent]);
return (
<div className={CLASS_NAME}>
<div className={`${CLASS_NAME}__header`}>
<SearchField
label="search"
placeholder="search"
onChange={handleSearchChange}
/>
<Link onClick={handleNewAppClick} to="/create-app">
<Button
className={`${CLASS_NAME}__add-button`}
buttonStyle={EnumButtonStyle.Primary}
icon="plus"
>
New app
</Button>
</Link>
</div>
<div className={`${CLASS_NAME}__title`}>{data?.apps.length} Apps</div>
{loading && <CircularProgress />}
{isEmpty(data?.apps) && !loading ? (
<div className={`${CLASS_NAME}__empty-state`}>
<SvgThemeImage image={EnumImages.AddApp} />
<div className={`${CLASS_NAME}__empty-state__title`}>
There are no apps to show
</div>
</div>
) : (
data?.apps.map((app) => {
return (
<ApplicationListItem
key={app.id}
app={app}
onDelete={handleDelete}
/>
);
})
)}
<Snackbar
open={Boolean(error || errorLoading)}
message={errorMessage}
onClose={clearError}
/>
</div>
);
}
Example #10
Source File: NewWorkspace.tsx From amplication with Apache License 2.0 | 4 votes |
NewWorkspace = ({ onWorkspaceCreated }: Props) => {
const { trackEvent } = useTracking();
const [createWorkspace, { error, loading }] = useMutation<DType>(
CREATE_WORKSPACE,
{
onCompleted: (data) => {
trackEvent({
eventName: "createWorkspace",
workspaceName: data.createWorkspace.name,
});
onWorkspaceCreated && onWorkspaceCreated(data.createWorkspace);
},
update(cache, { data }) {
if (!data) return;
const newWorkspace = data.createWorkspace;
cache.modify({
fields: {
workspaces(existingWorkspaceRefs = [], { readField }) {
const newWorkspaceRef = cache.writeFragment({
data: newWorkspace,
fragment: NEW_WORKSPACE_FRAGMENT,
});
if (
existingWorkspaceRefs.some(
(WorkspaceRef: Reference) =>
readField("id", WorkspaceRef) === newWorkspace.id
)
) {
return existingWorkspaceRefs;
}
return [...existingWorkspaceRefs, newWorkspaceRef];
},
},
});
},
}
);
const handleSubmit = useCallback(
(data: CreateWorkspaceType) => {
createWorkspace({
variables: {
data,
},
}).catch(console.error);
},
[createWorkspace]
);
const errorMessage = formatError(error);
return (
<div className={CLASS_NAME}>
<SvgThemeImage image={EnumImages.Entities} />
<div className={`${CLASS_NAME}__instructions`}>
Give your new workspace a descriptive name.
</div>
<Formik
initialValues={INITIAL_VALUES}
validate={(values: CreateWorkspaceType) =>
validate(values, FORM_SCHEMA)
}
onSubmit={handleSubmit}
validateOnMount
>
{(formik) => {
const handlers = {
SUBMIT: formik.submitForm,
};
return (
<Form>
<GlobalHotKeys keyMap={keyMap} handlers={handlers} />
<TextField
name="name"
label="New Workspace Name"
disabled={loading}
autoFocus
hideLabel
placeholder="Type New Workspace Name"
autoComplete="off"
/>
<Button
type="submit"
buttonStyle={EnumButtonStyle.Primary}
disabled={!formik.isValid || loading}
>
Create Workspace
</Button>
</Form>
);
}}
</Formik>
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}