Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mimir 1447 upcoming releases new repo #1668

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
7 changes: 6 additions & 1 deletion .xp-codegen/site/content-types/upcomingRelease/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ export interface UpcomingRelease {
/**
* Publisering
*/
date: string;
nextRelease: string;

/**
* Publisering (ikke bruk)
*/
date?: string;

/**
* Innholdstype
Expand Down
230 changes: 230 additions & 0 deletions src/main/resources/lib/ssb/parts/upcomingReleases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import type { Content } from '/lib/xp/content'
import { connect, multiRepoConnect, type MultiRepoConnection, type MultiRepoNodeQueryResponse } from '/lib/xp/node'
import { type Context, type ContextAttributes, get as getContext, type PrincipalKey } from '/lib/xp/context'
import { pageUrl } from '/lib/xp/portal'
import { getMainSubjectById, getMainSubjects, SubjectItem } from '../utils/subjectUtils'
import { type UpcomingRelease } from '/site/content-types'
import { ContentLight, Release } from '../repo/statisticVariant'
import { localize } from '/lib/xp/i18n'
import { addDays, getDate, getMonth, getYear, isWithinInterval } from 'date-fns'
import { getMainSubject } from '../utils/parentUtils'
import { forceArray } from '../utils/arrayUtils'
import { PreparedStatistics } from '../utils/variantUtils'

export function getUpcomingReleasesResults(req: XP.Request, numberOfDays: number | undefined, language: string) {
const allMainSubjects: Array<SubjectItem> = getMainSubjects(req, language)
const context: Context<ContextAttributes> = getContext()

const connection: MultiRepoConnection = multiRepoConnect({
sources: [
{
repoId: context.repository,
branch: context.branch,
principals: context.authInfo.principals as Array<PrincipalKey>,
},
{
repoId: 'no.ssb.statreg.statistics.variants',
branch: 'master',
principals: context.authInfo.principals as Array<PrincipalKey>,
},
],
})

const serverOffsetInMs: number =
app.config && app.config['serverOffsetInMs'] ? parseInt(app.config['serverOffsetInMs']) : 0
const serverTime: Date = new Date(new Date().getTime() + serverOffsetInMs)
const endDate: Date | undefined = numberOfDays ? addDays(serverTime, numberOfDays) : undefined

const results: MultiRepoNodeQueryResponse = connection.query({
count: 1000,
sort: [
{
field: 'data.nextRelease',
direction: 'ASC',
},
] as unknown as string,
query: {
range: {
field: 'data.nextRelease',
from: 'dateTime',
gte: serverTime,
lte: endDate,
},
} as unknown as string,
filters: {
boolean: {
must: [
{
hasValue: {
field: 'language',
values: language === 'nb' ? ['nb', 'nn'] : ['en'],
},
},
],
should: [
{
boolean: {
must: [
{
hasValue: {
field: 'data.articleType',
values: ['statistics'],
},
},
{
hasValue: {
field: 'data.status',
values: ['A'],
},
},
{
exists: {
field: 'data.statisticContentId',
},
},
],
},
},
// contentReleases
{
boolean: {
must: [
{
hasValue: {
field: 'type',
values: [`${app.name}:upcomingRelease`],
},
},
],
},
},
],
},
},
})

const contents: (Content<UpcomingRelease, object> | ContentLight<Release>)[] = results.hits.map((hit) =>
connect(hit).get<Content<UpcomingRelease, object> | ContentLight<Release>>(hit.id)
)

const upcomingReleases: Array<PreparedStatistics> = contents.map((content) =>
isContentUpcomingRelease(content)
? prepContentUpcomingRelease(content as Content<UpcomingRelease, object>, language, allMainSubjects)
: prepStatisticUpcomingRelease(content as ContentLight<Release>, language)
)

const filteredUpcomingReleasesStatistics = contents
.map((content) => filterUpcomingReleasesStatistics(content as ContentLight<Release>, language, serverTime, endDate))
.reduce((acc, curr) => {
if (curr.length) return acc.concat(curr)
else return acc
}, [])

const mergedStatisticsAndUpcomingStatisticsReleases = [
...upcomingReleases,
...(filteredUpcomingReleasesStatistics as Array<PreparedStatistics>),
].sort((a, b) => {
return new Date(a.date as string).getTime() - new Date(b.date as string).getTime()
})

return {
total: mergedStatisticsAndUpcomingStatisticsReleases.length,
upcomingReleases: mergedStatisticsAndUpcomingStatisticsReleases,
}
}

function isContentUpcomingRelease(content: unknown) {
return (content as Content).type === `${app.name}:upcomingRelease`
}

function prepContentUpcomingRelease(
content: Content<UpcomingRelease, object>,
language: string,
allMainSubjects: Array<SubjectItem>
): PreparedStatistics {
const date: string = content.data.nextRelease
johnnadeluy marked this conversation as resolved.
Show resolved Hide resolved
const mainSubjectItem: SubjectItem | null = getMainSubjectById(allMainSubjects, content.data.mainSubject)
const mainSubject: string = mainSubjectItem ? mainSubjectItem.title : ''
const contentType: string = content.data.contentType
? localize({
key: `contentType.${content.data.contentType}`,
locale: language,
})
: ''

return {
id: content._id,
name: content.displayName,
type: contentType,
date,
mainSubject: mainSubject,
variant: {
day: getDate(new Date(date)),
monthNumber: getMonth(new Date(date)),
year: getYear(new Date(date)),
},
statisticsPageUrl: content.data.href ? content.data.href : '',
}
}

function parseUpcomingStatistics(
statisticData: ContentLight<Release>['data'],
language: string,
date: string,
period: string
): PreparedStatistics {
return {
id: Number(statisticData.statisticId),
name: statisticData.name,
type: localize({
key: `contentType.${statisticData.articleType}`,
locale: language,
}),
date,
mainSubject: getMainSubject(statisticData.shortName, language),
variant: {
id: statisticData.statisticId,
day: getDate(new Date(date)),
monthNumber: getMonth(new Date(date)),
year: getYear(new Date(date)),
period: period,
frequency: statisticData.frequency,
},
statisticsPageUrl: pageUrl({
id: statisticData.statisticContentId as string,
}),
}
}

function filterUpcomingReleasesStatistics(
content: ContentLight<Release>,
language: string,
startDate: Date,
endDate: Date | undefined
): Array<PreparedStatistics | []> {
const filteredPreparedStatistics = content.data.upcomingReleases
? endDate
? forceArray(content.data.upcomingReleases).filter((release) =>
isWithinInterval(new Date(release.publishTime), { start: startDate, end: endDate })
)
: forceArray(content.data.upcomingReleases)
: []
if (filteredPreparedStatistics && filteredPreparedStatistics.length > 1) {
// remove the first upcoming release as it will have the same publishTime as the statistics' nextPeriod
filteredPreparedStatistics.shift()
return filteredPreparedStatistics.map((release) => {
const date = release.publishTime
return parseUpcomingStatistics(content.data, language, date, release.period)
})
}
return []
}

function prepStatisticUpcomingRelease(content: ContentLight<Release>, language: string): PreparedStatistics {
const date: string = content.data.nextRelease
return parseUpcomingStatistics(content.data, language, date, content.data.nextPeriod)
}
export interface PreparedStatisticsResults {
total: number
upcomingReleases: Array<PreparedStatistics>
}
25 changes: 23 additions & 2 deletions src/main/resources/lib/ssb/repo/statisticVariant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,20 @@ function prepareData({
allMainSubjectsStatistic,
allSubSubjectsStatistic,
}: CreateContentStatisticVariantParams): Release {
const upcomingReleases: Array<UpcomingRelease> = variant.upcomingReleases
? forceArray(variant.upcomingReleases).map((release) => {
const period: string = release.periodFrom
? capitalize(calculatePeriod(variant.frekvens, release.periodFrom, release.periodTo, language))
: ''
return {
publishTime: release.publishTime,
periodFrom: release.periodFrom,
periodTo: release.periodTo,
period,
}
})
: []

return {
statisticId: String(statistic.id),
variantId: String(variant.id),
Expand All @@ -268,7 +282,7 @@ function prepareData({
articleType: 'statistics', // allows this content to be filtered together with `Article.articleType`,
mainSubjects: allMainSubjectsStatistic.map((subject) => subject.name).filter(notNullOrUndefined),
subSubjects: allSubSubjectsStatistic.map((subject) => subject.name).filter(notNullOrUndefined),
upcomingReleases: variant.upcomingReleases,
upcomingReleases: upcomingReleases,
}
}

Expand Down Expand Up @@ -311,7 +325,7 @@ export interface Release {
articleType: 'statistics'
mainSubjects: Array<string> | string | undefined
subSubjects: Array<string> | string | undefined
upcomingReleases?: Array<ReleasesInListing>
upcomingReleases?: Array<UpcomingRelease>
}

export interface ContentLight<Data> {
Expand All @@ -335,3 +349,10 @@ interface CreateContentStatisticVariantParams {
allMainSubjectsStatistic: SubjectItem[]
allSubSubjectsStatistic: SubjectItem[]
}

interface UpcomingRelease {
publishTime: string
periodFrom: string
periodTo: string
period: string
}
10 changes: 5 additions & 5 deletions src/main/resources/lib/ssb/utils/variantUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,9 +577,9 @@ export interface VariantUtilsLib {
}

export interface PreparedStatistics {
id: number
id: number | string
name: string
shortName: string
shortName?: string
variant: PreparedVariant
type?: string
date?: string
Expand All @@ -589,12 +589,12 @@ export interface PreparedStatistics {
}

export interface PreparedVariant {
id: string
id?: string
day: number
monthNumber: number
year: number
frequency: string
period: string
frequency?: string
period?: string
}

export interface Release {
Expand Down
39 changes: 7 additions & 32 deletions src/main/resources/services/upcomingReleases/upcomingReleases.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,24 @@
import { StatisticInListing } from '../../lib/ssb/dashboard/statreg/types'
import { GroupedBy, PreparedStatistics, YearReleases, Release } from '../../lib/ssb/utils/variantUtils'
import { YearReleases } from '../../lib/ssb/utils/variantUtils'
import { getUpcomingReleasesResults } from '/lib/ssb/parts/upcomingReleases'

const { addMonthNames, groupStatisticsByYearMonthAndDay, prepareRelease, filterOnComingReleases, getUpcomingReleases } =
__non_webpack_require__('/lib/ssb/utils/variantUtils')
const { getAllStatisticsFromRepo } = __non_webpack_require__('../../lib/ssb/statreg/statistics')
const { addMonthNames, groupStatisticsByYearMonthAndDay } = __non_webpack_require__('/lib/ssb/utils/variantUtils')

exports.get = (req: XP.Request): XP.Response => {
// Get statistics
const statistics: Array<StatisticInListing> = getAllStatisticsFromRepo()
const upComingReleases: Array<Release> = getUpcomingReleases(statistics)
const count: number = req.params.count ? parseInt(req.params.count) : 2
const showAll = !!(req.params.showAll && req.params.showAll === 'true')

const count: number | undefined = req.params.count ? parseInt(req.params.count) : undefined
const language: string = req.params.language ? req.params.language : 'nb'
const numberOfDays: number = showAll ? getDaysToLatestRelease(upComingReleases) : count
// All statistics published today, and fill up with previous releases.
const releasesFiltered: Array<Release> = filterOnComingReleases(upComingReleases, numberOfDays, req.params.start)

// Choose the right variant and prepare the date in a way it works with the groupBy function
const releasesPrepped: Array<PreparedStatistics> = releasesFiltered.map((release: Release) =>
prepareRelease(release, language)
)
const upcomingReleases = getUpcomingReleasesResults(req, count, language).upcomingReleases

// group by year, then month, then day
const groupedByYearMonthAndDay: GroupedBy<GroupedBy<GroupedBy<PreparedStatistics>>> =
groupStatisticsByYearMonthAndDay(releasesPrepped)
const groupedByYearMonthAndDay = groupStatisticsByYearMonthAndDay(upcomingReleases)

// iterate and format month names
const groupedWithMonthNames: Array<YearReleases> = addMonthNames(groupedByYearMonthAndDay, language)

return {
status: 200,
contentType: 'application/json',
body: {
total: upcomingReleases.length,
releases: groupedWithMonthNames,
count,
},
}
}

function getDaysToLatestRelease(upComingReleases: Array<Release>): number {
const lastUpcomingRelease: Release = upComingReleases[upComingReleases.length - 1]
const today: Date = new Date()
const releaseDate: Date = new Date(lastUpcomingRelease.publishTime)
const diff: number = Math.abs(today.getTime() - releaseDate.getTime())
const diffDays: number = Math.ceil(diff / (1000 * 3600 * 24))
return diffDays
}
Loading