Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/content-insights/src/components/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const Dashboard = () => {

const metricsCalculator = new MetricsCalculator(entries, scheduledActions, {
needsUpdateMonths: installation.needsUpdateMonths,
needsUpdateContentTypes: installation.needsUpdateContentTypes,
recentlyPublishedDays: installation.recentlyPublishedDays,
timeToPublishDays: installation.timeToPublishDays,
});
Expand Down
15 changes: 11 additions & 4 deletions apps/content-insights/src/hooks/useNeedsUpdateContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ export function useNeedsUpdate(
contentTypes: Map<string, ContentTypeProps>
): UseNeedsUpdateResult {
const sdk = useSDK<HomeAppSDK | PageAppSDK>();
const needsUpdateMonths =
((sdk.parameters.installation ?? {}) as AppInstallationParameters).needsUpdateMonths ?? 6;
const installation = (sdk.parameters.installation ?? {}) as AppInstallationParameters;
const needsUpdateMonths = installation.needsUpdateMonths ?? 6;
const needsUpdateContentTypes = installation.needsUpdateContentTypes ?? [];
const defaultLocale = sdk.locales.default;

Comment thread
harikakondur marked this conversation as resolved.
const filteredEntries = useMemo(
Expand All @@ -50,10 +51,16 @@ export function useNeedsUpdate(
const updatedAt = parseDate(entry?.sys?.updatedAt);
if (!updatedAt) return false;
const thresholdDate = subMonths(new Date(), needsUpdateMonths);
if (updatedAt.getTime() >= thresholdDate.getTime()) return false;

return updatedAt.getTime() < thresholdDate.getTime();
if (needsUpdateContentTypes.length > 0) {
const contentTypeId = entry.sys.contentType?.sys?.id;
if (!contentTypeId || !needsUpdateContentTypes.includes(contentTypeId)) return false;
}
Comment thread
harikakondur marked this conversation as resolved.
Outdated

return true;
}),
[entries, needsUpdateMonths]
[entries, needsUpdateMonths, needsUpdateContentTypes]
);

const userIds = getUniqueUserIdsFromEntries(filteredEntries);
Expand Down
21 changes: 20 additions & 1 deletion apps/content-insights/src/locations/ConfigScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import TextInputInteger from '../components/TextInputInteger';

export interface AppInstallationParameters {
defaultContentTypes?: string[];
needsUpdateContentTypes?: string[];
needsUpdateMonths?: number;
recentlyPublishedDays?: number;
showUpcomingReleases?: boolean;
Expand All @@ -40,6 +41,7 @@ export interface AppInstallationParameters {
const ConfigScreen = () => {
const [parameters, setParameters] = useState<AppInstallationParameters>({});
const [selectedContentTypes, setSelectedContentTypes] = useState<ContentType[]>([]);
const [needsUpdateContentTypes, setNeedsUpdateContentTypes] = useState<ContentType[]>([]);
const sdk = useSDK<ConfigAppSDK>();

const [errors, setErrors] = useState<Record<string, string>>({});
Expand Down Expand Up @@ -86,10 +88,11 @@ const ConfigScreen = () => {
parameters: {
...parameters,
defaultContentTypes: selectedContentTypes.map((ct) => ct.id),
needsUpdateContentTypes: needsUpdateContentTypes.map((ct) => ct.id),
},
targetState: currentState,
};
}, [parameters, selectedContentTypes, sdk]);
}, [parameters, selectedContentTypes, needsUpdateContentTypes, sdk]);

useEffect(() => {
sdk.app.onConfigure(() => onConfigure());
Expand Down Expand Up @@ -181,6 +184,22 @@ const ConfigScreen = () => {
</FormControl.HelpText>
</FormControl>

<FormControl marginBottom="spacingL">
<FormControl.Label>
Content types included in &quot;Needs update&quot;
</FormControl.Label>
<ContentTypeMultiSelect
selectedContentTypes={needsUpdateContentTypes}
setSelectedContentTypes={setNeedsUpdateContentTypes}
sdk={sdk}
initialSelectedIds={parameters.needsUpdateContentTypes}
/>
<FormControl.HelpText>
Only entries of the selected content types will count toward the &quot;Needs
update&quot; metric. Leave empty to include all content types.
</FormControl.HelpText>
</FormControl>

<FormControl
marginBottom="spacingL"
isRequired
Expand Down
12 changes: 10 additions & 2 deletions apps/content-insights/src/metrics/MetricsCalculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class MetricsCalculator {
private readonly scheduledActions: ReadonlyArray<ScheduledActionProps>;
private readonly now: Date; // to maintain all the metrics consistent at the same current time
private readonly needsUpdateMonths: number;
private readonly needsUpdateContentTypes: readonly string[];
private readonly recentlyPublishedDays: number;
private readonly timeToPublishDays: number;

Expand All @@ -20,6 +21,7 @@ export class MetricsCalculator {
scheduledActions: ReadonlyArray<ScheduledActionProps>,
options?: {
needsUpdateMonths?: number;
needsUpdateContentTypes?: string[];
recentlyPublishedDays?: number;
timeToPublishDays?: number;
}
Expand All @@ -28,6 +30,7 @@ export class MetricsCalculator {
this.scheduledActions = scheduledActions;
this.now = new Date();
this.needsUpdateMonths = options?.needsUpdateMonths ?? NEEDS_UPDATE_MONTHS_RANGE.min;
this.needsUpdateContentTypes = options?.needsUpdateContentTypes ?? [];
this.recentlyPublishedDays =
options?.recentlyPublishedDays ?? RECENTLY_PUBLISHED_DAYS_RANGE.min;
this.timeToPublishDays = options?.timeToPublishDays ?? TIME_TO_PUBLISH_DAYS_RANGE.min;
Expand Down Expand Up @@ -167,9 +170,14 @@ export class MetricsCalculator {
for (const entry of this.entries) {
const updatedAt = parseDate(entry?.sys?.updatedAt);
if (!updatedAt) continue;
if (updatedAt.getTime() < cutoff.getTime()) {
count += 1;
if (updatedAt.getTime() >= cutoff.getTime()) continue;

if (this.needsUpdateContentTypes.length > 0) {
const contentTypeId = entry.sys.contentType?.sys?.id;
if (!contentTypeId || !this.needsUpdateContentTypes.includes(contentTypeId)) continue;
}

count += 1;
Comment thread
harikakondur marked this conversation as resolved.
}

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ describe('Config Screen component', () => {
timeToPublishDays: TIME_TO_PUBLISH_DAYS_RANGE.min,
showUpcomingReleases: true,
defaultContentTypes: [],
needsUpdateContentTypes: [],
},
targetState: {},
});
Expand Down
56 changes: 56 additions & 0 deletions apps/content-insights/test/metrics/MetricsCalculator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,5 +254,61 @@ describe('MetricsCalculator', () => {

expect(metric?.value).toBe('1');
});

it('filters by content type when needsUpdateContentTypes is set', () => {
const entries: EntryProps[] = [
{
sys: {
updatedAt: daysAgo(200),
contentType: { sys: { id: 'blogPost' } },
},
} as unknown as EntryProps,
{
sys: {
updatedAt: daysAgo(200),
contentType: { sys: { id: 'navigationItem' } },
},
} as unknown as EntryProps,
{
sys: {
updatedAt: daysAgo(200),
contentType: { sys: { id: 'blogPost' } },
},
} as unknown as EntryProps,
];

const calculator = new MetricsCalculator(entries, [], {
needsUpdateMonths: 6,
needsUpdateContentTypes: ['blogPost'],
});
const metric = calculator.getAllMetrics().find((m) => m.title === 'Needs update');

expect(metric?.value).toBe('2');
});

it('includes all content types when needsUpdateContentTypes is empty', () => {
const entries: EntryProps[] = [
{
sys: {
updatedAt: daysAgo(200),
contentType: { sys: { id: 'blogPost' } },
},
} as unknown as EntryProps,
{
sys: {
updatedAt: daysAgo(200),
contentType: { sys: { id: 'navigationItem' } },
},
} as unknown as EntryProps,
];

const calculator = new MetricsCalculator(entries, [], {
needsUpdateMonths: 6,
needsUpdateContentTypes: [],
});
const metric = calculator.getAllMetrics().find((m) => m.title === 'Needs update');

expect(metric?.value).toBe('2');
});
});
});
Loading