Skip to content

Commit

Permalink
Merge pull request #28 from webbio/feat/NP-151_urlAdditionAndRetriggers
Browse files Browse the repository at this point in the history
Feat/np 151 url addition and retriggers
  • Loading branch information
Martijn-Schoenmaker-Webbio authored Jan 26, 2024
2 parents c6c4303 + 363924e commit bc86b80
Show file tree
Hide file tree
Showing 13 changed files with 43 additions and 65 deletions.
1 change: 1 addition & 0 deletions src/plugins/strapi-plugin-internal-links/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default ({ env }) => {
useSinglePageType: 'api::page.page', // Optional option to use a single page type like the page builder (without page builder options)
defaultNoTitle: "undefined | boolean" // When enabled this will hide titles by default for the field
enableUrlAddition: "undefined | boolean" // When enabled this will show an extra input for url additions. This text will be put at the end of the url. This can by used for url params.
noUrlValidation: "undefined | boolean" // When enabled no url validation will happen on external url input.
pageBuilder: {
enabled: true, // When enabled, pageBuilder plugin logic is applied.
pageUid: 'undefined | string',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState, useLayoutEffect, useEffect, ChangeEvent } from 'react';
import escapeRegExp from 'lodash/escapeRegExp';
import * as yup from 'yup';
import { useIntl } from 'react-intl';
import { ReactSelect } from '@strapi/helper-plugin';
Expand All @@ -16,7 +15,6 @@ import { PageSearch } from './page-select';
import { Platform } from '../../api/platform';
import { IInternalLinkAttribute } from '..';
import { useGetConfig } from '../../api/config';
import { useDebounce } from '../../utils/use-debounce';

interface IProps extends Omit<IUseInternalLinkInputReturn, 'initialLink' | 'isInitialData' | 'resetInternalLink'> {
attributeOptions?: IInternalLinkAttribute['options'];
Expand Down Expand Up @@ -45,7 +43,6 @@ const InternalLinkForm = ({ link, setLink, errors, setErrors, attributeOptions }
const { page, pageId, setPageId, pageOptionsIsLoading } = usePageOptions(contentType, link.targetContentTypeId);
const { platform, setPlatformId, platformOptions, platformOptionsIsLoading, platformOptionsIsFetching } =
usePlatformOptions({ page, pageOptionsIsLoading });
const debouncedUrlAddition = useDebounce(link?.urlAddition, 300);
const [isExternalTab, setIsExternalTab] = useState<boolean>(link.type === 'external');
const translationLinkKey = !isExternalTab ? 'generated-link' : 'link';
const shouldShowTitle =
Expand All @@ -66,20 +63,6 @@ const InternalLinkForm = ({ link, setLink, errors, setErrors, attributeOptions }
}));
};

useEffect(() => {
if (debouncedUrlAddition !== link?.initialUrlAddition) {
const linkWithoutAddition = getLinkWithoutAddition(link?.url, link?.initialUrlAddition);

if (linkWithoutAddition) {
setLink({
...link,
initialUrlAddition: debouncedUrlAddition,
url: `${linkWithoutAddition}${debouncedUrlAddition || ''}`
});
}
}
}, [debouncedUrlAddition]);

useEffect(() => {
if (pluginConfig && useSinglePageType) {
setContentTypeUid(pluginConfig.pageBuilder?.pageUid || pluginConfig.useSinglePageType);
Expand Down Expand Up @@ -225,9 +208,10 @@ const InternalLinkForm = ({ link, setLink, errors, setErrors, attributeOptions }
};

const onUrlAdditionChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const linkValue = (event.target satisfies HTMLInputElement).value;
const value = (event.target satisfies HTMLInputElement).value;

if (link.url) {
setLink((value) => ({ ...value, urlAddition: linkValue }));
setLink((v) => ({ ...v, urlAddition: value }));
}
};

Expand All @@ -244,16 +228,6 @@ const InternalLinkForm = ({ link, setLink, errors, setErrors, attributeOptions }
}
}, [contentType?.domain, page]);

useEffect(() => {
if (!link?.urlAddition && !pageOptionsIsLoading && link?.domain) {
setLink((previousValue) => ({
...previousValue,
urlAddition: getInitialUrlAddition(pageOptionsIsLoading, link?.domain, link?.url, page?.slugLabel),
initialUrlAddition: getInitialUrlAddition(pageOptionsIsLoading, link?.domain, link?.url, page?.slugLabel)
}));
}
}, [pageOptionsIsLoading, link?.domain, link?.url, page?.slugLabel]);

return (
<Stack spacing={6}>
<ToggleCheckbox
Expand Down Expand Up @@ -373,7 +347,7 @@ const InternalLinkForm = ({ link, setLink, errors, setErrors, attributeOptions }
/>
)}

{pluginConfig?.enableUrlAddition && (
{pluginConfig?.enableUrlAddition && !isExternalTab && (
<Field name="urlAddition" id="urlAddition">
<FieldLabel>
{formatMessage({
Expand Down Expand Up @@ -449,26 +423,3 @@ const InternalLinkForm = ({ link, setLink, errors, setErrors, attributeOptions }
};

export default InternalLinkForm;

export const getInitialUrlAddition = (
isLoading?: boolean,
domain?: string,
url?: string,
pageSlug?: string
): string => {
if (!url || !pageSlug || !domain || isLoading) return '';

let formedUrl = [domain, pageSlug].filter(Boolean).join('/');
const reg = new RegExp(`^${escapeRegExp(formedUrl)}`, 'g');

return url.replace(reg, '');
};

export const getLinkWithoutAddition = (url?: string, initialUrlAddition?: string): string => {
if (!url) return '';

const reg = new RegExp(`${escapeRegExp(initialUrlAddition)}$`, 'g');
const linkWithoutAddition = initialUrlAddition ? url.replace(reg, '') : url;

return linkWithoutAddition;
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { InputGroup, Actions } from './styles';
import { useGetConfig } from '../../api/config';
import { useGetPlatforms } from '../../api/platform';
import { useGetPlatformRelation } from '../../api/platform-relation';
import { getLinkWithAddition } from '../../utils/url-addition';

export interface IInternalLinkAttribute {
customField: string;
Expand All @@ -32,7 +33,6 @@ export interface IInternalLinkAttribute {
slug?: string;
'link-regex'?: string;
noTitle?: boolean;
noLinkCheck?: boolean;
};
}

Expand Down Expand Up @@ -194,7 +194,7 @@ const InternalLinkInput = ({
aria-label={formatMessage({
id: getTrad('internal-link.input.aria-label')
})}
value={link.url}
value={getLinkWithAddition(link.url, link.urlAddition)}
required={required}
labelAction={labelAction}
disabled
Expand All @@ -220,7 +220,7 @@ const InternalLinkInput = ({
aria-label={formatMessage({
id: getTrad('internal-link.input.aria-label')
})}
value={link.url}
value={getLinkWithAddition(link.url, link.urlAddition)}
onClick={() => setShowModal(true)}
required={required}
disabled
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const getLinkWithAddition = (url?: string, urlAddition?: string): string => [url, urlAddition].filter(Boolean).join('');

export { getLinkWithAddition };
2 changes: 1 addition & 1 deletion src/plugins/strapi-plugin-internal-links/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@webbio/strapi-plugin-internal-links",
"version": "1.3.4",
"version": "1.3.9",
"description": "A custom field for Strapi that can create internal links",
"scripts": {
"develop": "tsc -p tsconfig.server.json -w",
Expand Down
5 changes: 4 additions & 1 deletion src/plugins/strapi-plugin-internal-links/server/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ export default async ({ strapi }: { strapi: Strapi }) => {
}

// This is added to prevent revalidation of internal links when the path isn't changed. The updatedPath state comes from the slug plugin
const state = { ...event.state, preventInternalLinksUpdate: !event?.params?.data?.state?.updatedPath };
const state = {
...event.state,
preventInternalLinksUpdate: !event?.params?.data?.state?.updatedPath
};

const uid = event.model.uid as Common.UID.ContentType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
},
"type": {
"type": "string"
},
"urlAddition": {
"type": "string"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
},
"type": {
"type": "string"
},
"urlAddition": {
"type": "string"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const updateInternalLinkSchema = object({
targetContentTypeId: number(),
url: string(),
text: string(),
type: string()
type: string(),
urlAddition: string()
})
});

Expand All @@ -25,7 +26,8 @@ const createInternalLinkSchema = object({
targetContentTypeId: number(),
url: string(),
text: string(),
type: string()
type: string(),
urlAddition: string()
})
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface InternalLink {
type?: string | null;
createdAt?: Date | null;
updatedAt?: Date | null;
urlAddition?: string | null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const mapInternalLinks = (
targetContentTypeId: internalLink?.targetContentTypeId ?? null,
url: internalLink?.url ?? null,
text: internalLink?.text ?? null,
type: internalLink?.type ?? null
type: internalLink?.type ?? null,
urlAddition: internalLink?.urlAddition ?? null
}));
};

Expand Down Expand Up @@ -186,7 +187,7 @@ const getInternalLinksFromCustomFields = async (
const updateManyInternalLinksByTarget = async (
targetContentTypeUid: string,
targetContentTypeId: string,
sanitizedEntity: any,
sanitizedEntity: Record<string, any>,
wysiwyg: boolean
) => {
const internalLinkContentType = wysiwyg
Expand All @@ -213,7 +214,10 @@ const updateManyInternalLinksByTarget = async (
]
},
data: {
url: updatedUrl
url: updatedUrl,
lifecycleState: {
exit: true
}
}
});
};
Expand Down Expand Up @@ -290,9 +294,13 @@ const updateSourceEntities = async (
const updateInternalLinksFromTargetContentType = async (
targetContentTypeUid: Common.UID.ContentType,
targetContentTypeId: string,
sanitizedEntity: any,
sanitizedEntity: Record<string, any>,
state?: Record<string, any>
) => {
if (state?.preventInternalLinksUpdate) {
return;
}

// Update links with new URL
await updateManyInternalLinksByTarget(targetContentTypeUid, targetContentTypeId, sanitizedEntity, true);
await updateManyInternalLinksByTarget(targetContentTypeUid, targetContentTypeId, sanitizedEntity, false);
Expand Down Expand Up @@ -347,6 +355,7 @@ const updateInternalLinksFromTargetContentType = async (
const entity: any = await getPopulatedEntity(uid, id);
const sanitizedEntity = await sanitizeEntity(entity, uid);
const updatedEntity = mapInternalLinksToEntity(sanitizedEntity, internalLinks);

await strapi.entityService.update(uid, id, {
data: {
...updatedEntity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const getDomain = (uid: string, entity?: Record<string, any>) => {
return pluginConfig.domains.default[environment];
};

const constructURL = async (uid: string, entity: Record<string, any>) => {
const constructURL = (uid: string, entity: Record<string, any>): string => {
const domain = getDomain(uid, entity);
const slug = getSlug(uid, entity);

Expand Down
2 changes: 2 additions & 0 deletions types/generated/contentTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export interface PluginInternalLinksInternalLink extends Schema.CollectionType {
url: Attribute.String;
text: Attribute.String;
type: Attribute.String;
urlAddition: Attribute.String;
createdAt: Attribute.DateTime;
updatedAt: Attribute.DateTime;
createdBy: Attribute.Relation<'plugin::internal-links.internal-link', 'oneToOne', 'admin::user'> &
Expand Down Expand Up @@ -437,6 +438,7 @@ export interface PluginInternalLinksInternalLinkWysiwyg extends Schema.Collectio
url: Attribute.String;
text: Attribute.String;
type: Attribute.String;
urlAddition: Attribute.String;
createdAt: Attribute.DateTime;
updatedAt: Attribute.DateTime;
createdBy: Attribute.Relation<'plugin::internal-links.internal-link-wysiwyg', 'oneToOne', 'admin::user'> &
Expand Down

0 comments on commit bc86b80

Please sign in to comment.