From a72815e6851355b934514ce8a540ad50e47ed351 Mon Sep 17 00:00:00 2001 From: Niko Lindroos Date: Mon, 13 Nov 2023 13:08:19 +0200 Subject: [PATCH 1/3] test: rearrange the MSW mocks LIIKUNTA-577. Map LinkedEvent and CMS queries and responses under their own folders. Improve the mocks so they would be more reusable. --- .../htmlToReact/HtmlToReact.stories.tsx | 2 +- .../__tests__/HtmlToReact.tests.tsx | 2 +- .../collection/__tests__/Collection.test.tsx | 2 +- src/core/pageContent/__tests__/Page.test.tsx | 2 +- src/mocks/handlers.ts | 6 +- src/mocks/queries/{ => cms}/page.ts | 2 +- src/mocks/queries/linkedEvents/eventsByIds.ts | 255 ++++++++++++++++++ .../{ => cms}/page/kukkuu-page-demosivu.json | 0 .../linkedEvents/eventMocks.ts} | 245 ----------------- 9 files changed, 263 insertions(+), 253 deletions(-) rename src/mocks/queries/{ => cms}/page.ts (78%) create mode 100644 src/mocks/queries/linkedEvents/eventsByIds.ts rename src/mocks/responses/{ => cms}/page/kukkuu-page-demosivu.json (100%) rename src/mocks/{queries/pageEventSelectionModule.ts => responses/linkedEvents/eventMocks.ts} (81%) diff --git a/src/common/components/htmlToReact/HtmlToReact.stories.tsx b/src/common/components/htmlToReact/HtmlToReact.stories.tsx index acce12a4..c9fa9d8f 100644 --- a/src/common/components/htmlToReact/HtmlToReact.stories.tsx +++ b/src/common/components/htmlToReact/HtmlToReact.stories.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { StoryFn, Meta } from '@storybook/react'; -import kukkuuTestPage from '../../../mocks/responses/page/kukkuu-page-demosivu.json'; +import kukkuuTestPage from '../../../mocks/responses/cms/page/kukkuu-page-demosivu.json'; import { HtmlToReact, HtmlToReactProps, TABLE_VARIANTS } from './HtmlToReact'; // Real embedded video content from the Wordpress headless CMS. diff --git a/src/common/components/htmlToReact/__tests__/HtmlToReact.tests.tsx b/src/common/components/htmlToReact/__tests__/HtmlToReact.tests.tsx index 2796da59..d2366186 100644 --- a/src/common/components/htmlToReact/__tests__/HtmlToReact.tests.tsx +++ b/src/common/components/htmlToReact/__tests__/HtmlToReact.tests.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { render } from '../../../utils/testingLibrary'; import { HtmlToReact, HtmlToReactProps } from '../HtmlToReact'; -import kukkuuPageDemosivu from '../../../../mocks/responses/page/kukkuu-page-demosivu.json'; +import kukkuuPageDemosivu from '../../../../mocks/responses/cms/page/kukkuu-page-demosivu.json'; const defaultAllowedUnsafeTags = ['iframe']; const defaultTrustedOrigins = [ diff --git a/src/core/collection/__tests__/Collection.test.tsx b/src/core/collection/__tests__/Collection.test.tsx index 48bb03ae..3a2e785a 100644 --- a/src/core/collection/__tests__/Collection.test.tsx +++ b/src/core/collection/__tests__/Collection.test.tsx @@ -8,7 +8,7 @@ import { eventIds, activeEvents, pastEventsWithoutEndingTime, -} from '../../../mocks/queries/pageEventSelectionModule'; +} from '../../../mocks/responses/linkedEvents/eventMocks'; import { CmsEndpoint } from '../../../storybook-common/constants'; import { getApolloConfig } from '../../../tests/apolloConfig'; diff --git a/src/core/pageContent/__tests__/Page.test.tsx b/src/core/pageContent/__tests__/Page.test.tsx index c5f65738..9747489e 100644 --- a/src/core/pageContent/__tests__/Page.test.tsx +++ b/src/core/pageContent/__tests__/Page.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { render, screen } from '../../../common/utils/testingLibrary'; import pageMock, { sidebarLinkList } from '../__mocks__/page.mock'; import { PageContent } from '../PageContent'; -import kukkuuPageDemosivu from '../../../mocks/responses/page/kukkuu-page-demosivu.json'; +import kukkuuPageDemosivu from '../../../mocks/responses/cms/page/kukkuu-page-demosivu.json'; import { PageType } from '../../../common/headlessService/types'; import { ConfigProvider } from '../../configProvider/ConfigProvider'; import { Config } from '../../configProvider/configContext'; diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 4ece0abd..f2d57987 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -1,4 +1,4 @@ -import { queryPage } from './queries/page'; -import { queryPageEventSelectioModule } from './queries/pageEventSelectionModule'; +import { queryPage } from './queries/cms/page'; +import { queryEventsByIds } from './queries/linkedEvents/eventsByIds'; -export const handlers = [queryPageEventSelectioModule(), queryPage()]; +export const handlers = [queryEventsByIds(), queryPage()]; diff --git a/src/mocks/queries/page.ts b/src/mocks/queries/cms/page.ts similarity index 78% rename from src/mocks/queries/page.ts rename to src/mocks/queries/cms/page.ts index 2db73b20..9c9701d6 100644 --- a/src/mocks/queries/page.ts +++ b/src/mocks/queries/cms/page.ts @@ -1,7 +1,7 @@ // eslint-disable-next-line import/no-extraneous-dependencies import { graphql } from 'msw'; -import kukkuuPageDemosivu from '../responses/page/kukkuu-page-demosivu.json'; +import kukkuuPageDemosivu from '../../responses/cms/page/kukkuu-page-demosivu.json'; export const queryPage = () => graphql.query('Page', (req, res, ctx) => { diff --git a/src/mocks/queries/linkedEvents/eventsByIds.ts b/src/mocks/queries/linkedEvents/eventsByIds.ts new file mode 100644 index 00000000..fe7717c2 --- /dev/null +++ b/src/mocks/queries/linkedEvents/eventsByIds.ts @@ -0,0 +1,255 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { graphql } from 'msw'; + +import { + activeEvents, + pastEvents, +} from '../../responses/linkedEvents/eventMocks'; + +/** + Query to fetch event selection module in the Carousel-component. + + Example query taken from the real response of Hobbies staging CMS: https://hobbies-graphql-proxy.test.hel.ninja/proxy/graphql. + The response is modified so that there are 2 ongoing events and the rest of them are in the past. + + query: + ``` + query EventsByIds($ids: [ID!]!, $eventType: [EventTypeId], $include: [String], $sort: String, $pageSize: Int, $page: Int, $start: String, $end: String) { + eventsByIds( + ids: $ids + eventType: $eventType + include: $include + sort: $sort + pageSize: $pageSize + page: $page + start: $start + end: $end + ) { + data { + ...eventCmsEventFields + __typename + } + meta { + count + next + previous + __typename + } + __typename + } + } + + fragment eventCmsEventFields on EventDetails { + id + internalId + audienceMinAge + audienceMaxAge + eventStatus + externalLinks { + name + link + __typename + } + images { + id + name + url + photographerName + __typename + } + subEvents { + internalId + __typename + } + typeId + superEvent { + internalId + __typename + } + inLanguage { + name { + ...localizedCmsEventFields + __typename + } + __typename + } + keywords { + ...keywordCmsEventFields + __typename + } + location { + ...placeCmsEventFields + __typename + } + offers { + ...offerCmsEventFields + __typename + } + name { + ...localizedCmsEventFields + __typename + } + description { + ...localizedCmsEventFields + __typename + } + shortDescription { + ...localizedCmsEventFields + __typename + } + endTime + startTime + publisher + provider { + ...localizedCmsEventFields + __typename + } + infoUrl { + ...localizedCmsEventFields + __typename + } + audience { + id + name { + ...localizedCmsEventFields + __typename + } + __typename + } + locationExtraInfo { + ...localizedCmsEventFields + __typename + } + enrolmentStartTime + enrolmentEndTime + remainingAttendeeCapacity + __typename + } + + fragment localizedCmsEventFields on LocalizedObject { + en + fi + sv + __typename + } + + fragment keywordCmsEventFields on Keyword { + id + internalId + dataSource + hasUpcomingEvents + name { + ...localizedCmsEventFields + __typename + } + __typename + } + + fragment placeCmsEventFields on Place { + id + divisions { + type + name { + ...localizedCmsEventFields + __typename + } + __typename + } + hasUpcomingEvents + internalId + email + infoUrl { + ...localizedCmsEventFields + __typename + } + name { + ...localizedCmsEventFields + __typename + } + addressLocality { + ...localizedCmsEventFields + __typename + } + streetAddress { + ...localizedCmsEventFields + __typename + } + postalCode + position { + coordinates + __typename + } + telephone { + ...localizedCmsEventFields + __typename + } + __typename + } + + fragment offerCmsEventFields on Offer { + isFree + price { + ...localizedCmsEventFields + __typename + } + description { + ...localizedCmsEventFields + __typename + } + infoUrl { + ...localizedCmsEventFields + __typename + } + __typename + } + } + ``` + + vars: + ``` + { + "ids": [ + "helsinki:agb5kr3nra", + "harrastushaku:14523_2023010215001630", + "harrastushaku:14503_2023010215001700", + "harrastushaku:14524_2023010315001700", + "harrastushaku:16143", + "harrastushaku:14526_2023010515001630" + ], + "pageSize": 6, + "include": [ + "in_language", + "keywords", + "location", + "audience" + ], + "eventType": [ + "General", + "Course" + ] + } + ``` +*/ +export const queryEventsByIds = () => + graphql.query('EventsByIds', (req, res, ctx) => { + const eventIdsFilter = req.variables.ids; + const events = [...activeEvents, ...pastEvents]; + // const data = eventIdsFilter?.length + // ? events.filter((event) => eventIdsFilter.includes(event.id)) + // : events; + const data = events.filter((event) => eventIdsFilter.includes(event.id)); + return res( + ctx.data({ + eventsByIds: { + data, + meta: { + count: data.length, + next: null, + previous: null, + __typename: 'Meta', + }, + __typename: 'EventListResponse', + }, + }), + ); + }); diff --git a/src/mocks/responses/page/kukkuu-page-demosivu.json b/src/mocks/responses/cms/page/kukkuu-page-demosivu.json similarity index 100% rename from src/mocks/responses/page/kukkuu-page-demosivu.json rename to src/mocks/responses/cms/page/kukkuu-page-demosivu.json diff --git a/src/mocks/queries/pageEventSelectionModule.ts b/src/mocks/responses/linkedEvents/eventMocks.ts similarity index 81% rename from src/mocks/queries/pageEventSelectionModule.ts rename to src/mocks/responses/linkedEvents/eventMocks.ts index 2f61c386..6848d03b 100644 --- a/src/mocks/queries/pageEventSelectionModule.ts +++ b/src/mocks/responses/linkedEvents/eventMocks.ts @@ -1,6 +1,3 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { graphql } from 'msw'; - /** The eventIds used as the query variables */ export const eventIds = [ 'helsinki:agb5kr3nra', @@ -1029,245 +1026,3 @@ export const pastEvents = [ __typename: 'EventDetails', }, ]; - -/** - Query to fetch event selection module in the Carousel-component. - - Example query taken from the real response of Hobbies staging CMS: https://hobbies-graphql-proxy.test.hel.ninja/proxy/graphql. - The response is modified so that there are 2 ongoing events and the rest of them are in the past. - - query: - ``` - query EventsByIds($ids: [ID!]!, $eventType: [EventTypeId], $include: [String], $sort: String, $pageSize: Int, $page: Int, $start: String, $end: String) { - eventsByIds( - ids: $ids - eventType: $eventType - include: $include - sort: $sort - pageSize: $pageSize - page: $page - start: $start - end: $end - ) { - data { - ...eventCmsEventFields - __typename - } - meta { - count - next - previous - __typename - } - __typename - } - } - - fragment eventCmsEventFields on EventDetails { - id - internalId - audienceMinAge - audienceMaxAge - eventStatus - externalLinks { - name - link - __typename - } - images { - id - name - url - photographerName - __typename - } - subEvents { - internalId - __typename - } - typeId - superEvent { - internalId - __typename - } - inLanguage { - name { - ...localizedCmsEventFields - __typename - } - __typename - } - keywords { - ...keywordCmsEventFields - __typename - } - location { - ...placeCmsEventFields - __typename - } - offers { - ...offerCmsEventFields - __typename - } - name { - ...localizedCmsEventFields - __typename - } - description { - ...localizedCmsEventFields - __typename - } - shortDescription { - ...localizedCmsEventFields - __typename - } - endTime - startTime - publisher - provider { - ...localizedCmsEventFields - __typename - } - infoUrl { - ...localizedCmsEventFields - __typename - } - audience { - id - name { - ...localizedCmsEventFields - __typename - } - __typename - } - locationExtraInfo { - ...localizedCmsEventFields - __typename - } - enrolmentStartTime - enrolmentEndTime - remainingAttendeeCapacity - __typename - } - - fragment localizedCmsEventFields on LocalizedObject { - en - fi - sv - __typename - } - - fragment keywordCmsEventFields on Keyword { - id - internalId - dataSource - hasUpcomingEvents - name { - ...localizedCmsEventFields - __typename - } - __typename - } - - fragment placeCmsEventFields on Place { - id - divisions { - type - name { - ...localizedCmsEventFields - __typename - } - __typename - } - hasUpcomingEvents - internalId - email - infoUrl { - ...localizedCmsEventFields - __typename - } - name { - ...localizedCmsEventFields - __typename - } - addressLocality { - ...localizedCmsEventFields - __typename - } - streetAddress { - ...localizedCmsEventFields - __typename - } - postalCode - position { - coordinates - __typename - } - telephone { - ...localizedCmsEventFields - __typename - } - __typename - } - - fragment offerCmsEventFields on Offer { - isFree - price { - ...localizedCmsEventFields - __typename - } - description { - ...localizedCmsEventFields - __typename - } - infoUrl { - ...localizedCmsEventFields - __typename - } - __typename - } - } - ``` - - vars: - ``` - { - "ids": [ - "helsinki:agb5kr3nra", - "harrastushaku:14523_2023010215001630", - "harrastushaku:14503_2023010215001700", - "harrastushaku:14524_2023010315001700", - "harrastushaku:16143", - "harrastushaku:14526_2023010515001630" - ], - "pageSize": 6, - "include": [ - "in_language", - "keywords", - "location", - "audience" - ], - "eventType": [ - "General", - "Course" - ] - } - ``` -*/ -export const queryPageEventSelectioModule = () => - graphql.query('EventsByIds', (req, res, ctx) => - res( - ctx.data({ - eventsByIds: { - data: [...activeEvents, ...pastEvents], - meta: { - count: 5, - next: null, - previous: null, - __typename: 'Meta', - }, - __typename: 'EventListResponse', - }, - }), - ), - ); From 63e60b0cea58cbfc43a0fa9956c40c101efc7fa6 Mon Sep 17 00:00:00 2001 From: Niko Lindroos Date: Tue, 14 Nov 2023 14:11:09 +0200 Subject: [PATCH 2/3] feat: event search collection replaces a start-param for past with the "now" LIIKUNTA-577 --- src/core/collection/Collection.tsx | 18 +- .../collection/__tests__/Collection.test.tsx | 120 +- src/core/collection/constants.ts | 1 + src/core/collection/utils.ts | 15 + src/mocks/handlers.ts | 3 +- src/mocks/queries/linkedEvents/eventList.ts | 263 ++ .../tapahtumat-eventlist-frontpage.json | 2239 +++++++++++++++++ 7 files changed, 2648 insertions(+), 11 deletions(-) create mode 100644 src/core/collection/constants.ts create mode 100644 src/mocks/queries/linkedEvents/eventList.ts create mode 100644 src/mocks/responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json diff --git a/src/core/collection/Collection.tsx b/src/core/collection/Collection.tsx index fd199cf3..23ae21a7 100644 --- a/src/core/collection/Collection.tsx +++ b/src/core/collection/Collection.tsx @@ -28,7 +28,12 @@ import { Link } from '../link/Link'; import { useVenuesByIdsQuery } from '../../common/venuesService/__generated__'; import { VenueType } from '../../common/venuesService/types'; import { LanguageCodeEnum } from '../../common/headlessService/types'; -import { getVenueIds, isEventClosed, normalizeParamsValues } from './utils'; +import { + convertDateStringInPastToNow, + getVenueIds, + isEventClosed, + normalizeParamsValues, +} from './utils'; import { DEFAULT_LOCALE } from '../../constants'; import { isPageType, isArticleType } from '../../common/headlessService/utils'; @@ -215,10 +220,17 @@ export function getEventCollectionCards({ export type EventSearchCollectionProps = Omit & { collection: EventSearchCollectionType; + convertPastDatesToNow?: boolean; }; +/** + * EventSearchCollection uses an (LinkedEvents) URL to make a API query to fetch the related events. + * + * Use `convertPastDatesToNow = true` to fix an issue (between the CMS and the LinkedEvents) when old ended events are shown. + */ export function EventSearchCollection({ collection, + convertPastDatesToNow = true, ...delegatedProps }: EventSearchCollectionProps) { const eventsApolloClient = useEventsApolloClientFromConfig(); @@ -238,8 +250,12 @@ export function EventSearchCollection({ ); const params = Object.fromEntries(searchParams.entries()); const normalizedParams = normalizeParamsValues(params); + const start = convertPastDatesToNow + ? convertDateStringInPastToNow(normalizedParams.start) + : normalizedParams.start; const variables = { ...normalizedParams, + start, pageSize, include: ['in_language', 'keywords', 'location', 'audience'], }; diff --git a/src/core/collection/__tests__/Collection.test.tsx b/src/core/collection/__tests__/Collection.test.tsx index 3a2e785a..de8d3a03 100644 --- a/src/core/collection/__tests__/Collection.test.tsx +++ b/src/core/collection/__tests__/Collection.test.tsx @@ -1,9 +1,13 @@ import React from 'react'; +import { addDays, addYears, subDays, subYears } from 'date-fns'; -import { EventSelectionCollectionType } from '../types'; +import { + EventSearchCollectionType, + EventSelectionCollectionType, +} from '../types'; import { render, screen, waitFor } from '../../../common/utils/testingLibrary'; import { server } from '../../../mocks/server'; -import { EventSelectionCollection } from '../Collection'; +import { EventSearchCollection, EventSelectionCollection } from '../Collection'; import { eventIds, activeEvents, @@ -11,6 +15,9 @@ import { } from '../../../mocks/responses/linkedEvents/eventMocks'; import { CmsEndpoint } from '../../../storybook-common/constants'; import { getApolloConfig } from '../../../tests/apolloConfig'; +import { frontPageCarouselVariables } from '../../../mocks/queries/linkedEvents/eventList'; +import tapahtumatEventListFrontPageCarousel from '../../../mocks/responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json'; +import * as CollectionUtils from '../utils'; // Establish API mocking before all tests. beforeAll(() => { @@ -18,6 +25,10 @@ beforeAll(() => { expect(activeEvents.length).toBe(2); }); +afterEach(() => { + jest.resetAllMocks(); +}); + describe('event selection module', () => { it('excludes the events that have already ended', async () => { const collection = { events: eventIds } as EventSelectionCollectionType; @@ -33,10 +44,8 @@ describe('event selection module', () => { }); // All the ongoing events should be shown - activeEvents.forEach(async (event) => { - expect( - await screen.findByRole('link', { name: event.name.fi }), - ).toBeInTheDocument(); + activeEvents.forEach((event) => { + expect(screen.getByText(event.name.fi)).toBeInTheDocument(); }); // Events without the ending time but a start time in the future are also included @@ -46,9 +55,7 @@ describe('event selection module', () => { // The events withoiut the ending time in the past are not pastEventsWithoutEndingTime.forEach((event) => { - expect( - screen.queryByRole('link', { name: event.name.fi }), - ).not.toBeInTheDocument(); + expect(screen.queryByText(event.name.fi)).not.toBeInTheDocument(); }); // No other cards than the ongoing events should be shown. @@ -59,3 +66,98 @@ describe('event selection module', () => { expect(screen.getAllByRole('link').length).toBe(activeEvents.length); }); }); + +describe('event search module', () => { + it.each( + [ + new Date(), + subDays(new Date(), 1), + subDays(new Date(), 10), + subDays(new Date(), 100), + subYears(new Date(), 1), + subYears(new Date(), 10), + subYears(new Date(), 100), + ].map((d) => d.toISOString().substring(0, 'YYYY-MM-DD'.length)), + )( + 'replace the start-parameter past date-string value "%s" with "now"', + async (dateInPast) => { + const convertDateStringInPastToNowSpy = jest.spyOn( + CollectionUtils, + 'convertDateStringInPastToNow', + ); + const { data } = tapahtumatEventListFrontPageCarousel.eventList; + const variables = { + ...Object.fromEntries(frontPageCarouselVariables), + start: dateInPast, + }; + const eventSearchUrl = new URLSearchParams(variables).toString(); + const collection = { url: eventSearchUrl } as EventSearchCollectionType; + + render( + , + null, + { ...getApolloConfig(CmsEndpoint.events) }, + ); + + await waitFor(() => { + expect(screen.queryByText(/Page is loading/)).not.toBeInTheDocument(); + }); + + // All the events should be shown + data.forEach((event) => { + expect(screen.getByText(event.name.fi)).toBeInTheDocument(); + }); + + expect(convertDateStringInPastToNowSpy).toBeCalledWith(dateInPast); + expect(convertDateStringInPastToNowSpy).toHaveReturnedWith('now'); + }, + ); + + it.each( + [ + addDays(new Date(), 1), + addDays(new Date(), 10), + addDays(new Date(), 100), + addYears(new Date(), 1), + addYears(new Date(), 10), + addYears(new Date(), 100), + 'now', + 'today', + ].map((d) => + typeof d === 'string' ? d : d.toISOString().substring(0, 10), + ), + )( + 'dont replace the start-parameter future date-string value "%s"', + async (dateInFuture) => { + const convertDateStringInPastToNowSpy = jest.spyOn( + CollectionUtils, + 'convertDateStringInPastToNow', + ); + const { data } = tapahtumatEventListFrontPageCarousel.eventList; + const variables = { + ...Object.fromEntries(frontPageCarouselVariables), + start: dateInFuture, + }; + const eventSearchUrl = new URLSearchParams(variables).toString(); + const collection = { url: eventSearchUrl } as EventSearchCollectionType; + + render( + , + null, + { ...getApolloConfig(CmsEndpoint.events) }, + ); + + await waitFor(() => { + expect(screen.queryByText(/Page is loading/)).not.toBeInTheDocument(); + }); + + // All the events should be shown + data.forEach((event) => { + expect(screen.getByText(event.name.fi)).toBeInTheDocument(); + }); + + expect(convertDateStringInPastToNowSpy).toBeCalledWith(dateInFuture); + expect(convertDateStringInPastToNowSpy).toHaveReturnedWith(dateInFuture); + }, + ); +}); diff --git a/src/core/collection/constants.ts b/src/core/collection/constants.ts new file mode 100644 index 00000000..ca2cb460 --- /dev/null +++ b/src/core/collection/constants.ts @@ -0,0 +1 @@ +export const LINKEDEVENTS_DATE_NOW = 'now'; diff --git a/src/core/collection/utils.ts b/src/core/collection/utils.ts index e669245f..2e4205e4 100644 --- a/src/core/collection/utils.ts +++ b/src/core/collection/utils.ts @@ -2,6 +2,7 @@ import isPast from 'date-fns/isPast'; import { EventType } from '../../common/eventsService/types'; import normalizeKeys from '../../linkedEvents/utils/normalizeKeys'; +import { LINKEDEVENTS_DATE_NOW } from './constants'; export function getVenueIds(ids: number[]): string[] { return ids.map((id) => `tprek:${id}`); @@ -41,3 +42,17 @@ export const normalizeParamsValues = (params: Record) => { return normalizedParams; }; + +export function isValidDate(dateString: string) { + return !Number.isNaN(Date.parse(dateString)); +} + +export const convertDateStringInPastToNow = (start: string): string => { + const startDate = new Date(start); + const now = new Date(); + + if (isValidDate(start) && startDate <= now) { + return LINKEDEVENTS_DATE_NOW; + } + return start; +}; diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index f2d57987..3491cebf 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -1,4 +1,5 @@ import { queryPage } from './queries/cms/page'; +import { queryEventList } from './queries/linkedEvents/eventList'; import { queryEventsByIds } from './queries/linkedEvents/eventsByIds'; -export const handlers = [queryEventsByIds(), queryPage()]; +export const handlers = [queryEventList(), queryEventsByIds(), queryPage()]; diff --git a/src/mocks/queries/linkedEvents/eventList.ts b/src/mocks/queries/linkedEvents/eventList.ts new file mode 100644 index 00000000..921ecaaf --- /dev/null +++ b/src/mocks/queries/linkedEvents/eventList.ts @@ -0,0 +1,263 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { graphql } from 'msw'; + +import tapahtumatEventListFrontPageCarousel from '../../responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json'; + +export const frontPageCarouselVariables = new URLSearchParams({ + keyword: + 'yso:p1808,yso:p18434,yso:p27962,yso:p3064,yso:p20421,yso:p6422,yso:p2162,yso:p768,yso:p18718,yso:p24765,yso:p5470,yso:p23218,yso:p2841,yso:p29817,yso:p12257,yso:p3065', + location: + 'tprek:7265,tprek:7256,tprek:7255,tprek:8740,tprek:7259,tprek:7260,tprek:7254,tprek:20633,tprek:7258', + division: 'kunta:helsinki', + sort: 'end_time', + superEventType: 'umbrella,none', + start: 'now', + pageSize: '9', + include: 'in_language,keywords,location,audience', +}); + +/** + Query to fetch event selection module in the Carousel-component. + + Example query taken from the real response of Hobbies staging CMS: https://hobbies-graphql-proxy.test.hel.ninja/proxy/graphql. + The response is modified so that there are 2 ongoing events and the rest of them are in the past. + + query: + ``` + query EventList($eventType: [EventTypeId], $internetBased: Boolean, $suitableFor: [Int], $allOngoing: Boolean, $allOngoingAnd: [String], $division: [String], $end: String, $endsAfter: String, $endsBefore: String, $inLanguage: String, $include: [String], $isFree: Boolean, $keyword: [String], $keywordAnd: [String], $keywordOrSet1: [String], $keywordOrSet2: [String], $keywordOrSet3: [String], $keywordNot: [String], $language: String, $localOngoingAnd: [String], $location: [String], $page: Int, $pageSize: Int, $publisher: ID, $sort: String, $start: String, $startsAfter: String, $startsBefore: String, $superEvent: ID, $superEventType: [String], $text: String, $translation: String) { + eventList( + eventType: $eventType + internetBased: $internetBased + suitableFor: $suitableFor + allOngoing: $allOngoing + allOngoingAnd: $allOngoingAnd + division: $division + end: $end + endsAfter: $endsAfter + endsBefore: $endsBefore + include: $include + inLanguage: $inLanguage + isFree: $isFree + keyword: $keyword + keywordAnd: $keywordAnd + keywordOrSet1: $keywordOrSet1 + keywordOrSet2: $keywordOrSet2 + keywordOrSet3: $keywordOrSet3 + keywordNot: $keywordNot + language: $language + localOngoingAnd: $localOngoingAnd + location: $location + page: $page + pageSize: $pageSize + publisher: $publisher + sort: $sort + start: $start + startsAfter: $startsAfter + startsBefore: $startsBefore + superEvent: $superEvent + superEventType: $superEventType + text: $text + translation: $translation + ) { + meta { + count + next + previous + __typename + } + data { + ...eventCmsEventFields + __typename + } + __typename + } + } + + fragment eventCmsEventFields on EventDetails { + id + internalId + audienceMinAge + audienceMaxAge + eventStatus + externalLinks { + name + link + __typename + } + images { + id + name + url + photographerName + __typename + } + subEvents { + internalId + __typename + } + typeId + superEvent { + internalId + __typename + } + inLanguage { + name { + ...localizedCmsEventFields + __typename + } + __typename + } + keywords { + ...keywordCmsEventFields + __typename + } + location { + ...placeCmsEventFields + __typename + } + offers { + ...offerCmsEventFields + __typename + } + name { + ...localizedCmsEventFields + __typename + } + description { + ...localizedCmsEventFields + __typename + } + shortDescription { + ...localizedCmsEventFields + __typename + } + endTime + startTime + publisher + provider { + ...localizedCmsEventFields + __typename + } + infoUrl { + ...localizedCmsEventFields + __typename + } + audience { + id + name { + ...localizedCmsEventFields + __typename + } + __typename + } + locationExtraInfo { + ...localizedCmsEventFields + __typename + } + enrolmentStartTime + enrolmentEndTime + remainingAttendeeCapacity + __typename + } + + fragment localizedCmsEventFields on LocalizedObject { + en + fi + sv + __typename + } + + fragment keywordCmsEventFields on Keyword { + id + internalId + dataSource + hasUpcomingEvents + name { + ...localizedCmsEventFields + __typename + } + __typename + } + + fragment placeCmsEventFields on Place { + id + divisions { + type + name { + ...localizedCmsEventFields + __typename + } + __typename + } + hasUpcomingEvents + internalId + email + infoUrl { + ...localizedCmsEventFields + __typename + } + name { + ...localizedCmsEventFields + __typename + } + addressLocality { + ...localizedCmsEventFields + __typename + } + streetAddress { + ...localizedCmsEventFields + __typename + } + postalCode + position { + coordinates + __typename + } + telephone { + ...localizedCmsEventFields + __typename + } + __typename + } + + fragment offerCmsEventFields on Offer { + isFree + price { + ...localizedCmsEventFields + __typename + } + description { + ...localizedCmsEventFields + __typename + } + infoUrl { + ...localizedCmsEventFields + __typename + } + __typename + } + ``` + + vars: + ``` + { + "keyword": "yso:p1808,yso:p18434,yso:p27962,yso:p3064,yso:p20421,yso:p6422,yso:p2162,yso:p768,yso:p18718,yso:p24765,yso:p5470,yso:p23218,yso:p2841,yso:p29817,yso:p12257,yso:p3065", + "location": "tprek:7265,tprek:7256,tprek:7255,tprek:8740,tprek:7259,tprek:7260,tprek:7254,tprek:20633,tprek:7258", + "division": "kunta:helsinki", + "sort": "end_time", + "superEventType": "umbrella,none", + "start": "now", + "pageSize": 9, + "include": [ + "in_language", + "keywords", + "location", + "audience" + ] + } + ``` +*/ +export const queryEventList = () => + graphql.query('EventList', (req, res, ctx) => + res(ctx.data(tapahtumatEventListFrontPageCarousel)), + ); diff --git a/src/mocks/responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json b/src/mocks/responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json new file mode 100644 index 00000000..1f8201fb --- /dev/null +++ b/src/mocks/responses/linkedEvents/eventList/tapahtumat-eventlist-frontpage.json @@ -0,0 +1,2239 @@ +{ + "eventList": { + "meta": { + "count": 167, + "next": "https://api.hel.fi/linkedevents/v1/event/?division=kunta%3Ahelsinki&event_type=General&include=in_language%2Ckeywords%2Clocation%2Caudience&keyword=yso%3Ap1808%2Cyso%3Ap18434%2Cyso%3Ap27962%2Cyso%3Ap3064%2Cyso%3Ap20421%2Cyso%3Ap6422%2Cyso%3Ap2162%2Cyso%3Ap768%2Cyso%3Ap18718%2Cyso%3Ap24765%2Cyso%3Ap5470%2Cyso%3Ap23218%2Cyso%3Ap2841%2Cyso%3Ap29817%2Cyso%3Ap12257%2Cyso%3Ap3065&location=tprek%3A7265%2Ctprek%3A7256%2Ctprek%3A7255%2Ctprek%3A8740%2Ctprek%3A7259%2Ctprek%3A7260%2Ctprek%3A7254%2Ctprek%3A20633%2Ctprek%3A7258&page=2&page_size=9&sort=end_time&start=now&super_event_type=umbrella%2Cnone", + "previous": null, + "__typename": "Meta" + }, + "data": [ + { + "id": "kulke:60170", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:60170/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "92851", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_733550.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:32", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:32/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Tanssi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:33", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:33/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Teatteri", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:351", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:351/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Teatteri ja sirkus", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1278", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1278/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "dance (performing arts)", + "fi": "tanssi", + "sv": "dans", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p2625", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p2625/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "theatre (art forms)", + "fi": "teatteritaide", + "sv": "teaterkonst", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:7258", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Ullanlinna", + "sv": "Ulrikasborg", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Kaartinkaupunki", + "sv": "Gardesstaden", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Kaartinkaupunki", + "sv": "Gardesstaden", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:7258/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Theatre", + "fi": "teatteri", + "sv": "teatern", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Kasarmikatu 46-48", + "fi": "Kasarmikatu 46-48", + "sv": "Kaserngatan 46-48", + "__typename": "LocalizedObject" + }, + "postalCode": "00130", + "position": { + "coordinates": [24.947306, 60.16663], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 9 310 36563", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": false, + "price": { + "en": null, + "fi": "42,50 €", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": null, + "infoUrl": { + "en": null, + "fi": "https://mocked-ticket-service.fi/event/name-17157486", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Offer" + } + ], + "name": { + "en": null, + "fi": "Mahdoton rakkaus – Tangonäytelmä", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": { + "en": null, + "fi": "

Tangonäytelmä Mahdoton Rakkaus on esitys, joka nostaa esille uutta kotimaista tangomusiikkia unohtamatta genren kuolemattomia klassikoita. Ohjauksesta vastaa Sari Siikander, käsikirjoituksesta Taina West ja musiikin sovituksista Jasse Varpama. Tuotanto Elevent Group Oy.

Mahdoton rakkaus on tangomusiikin siivittämä kertomus ystävyydestä, rakastumisesta, sydänsuruista ja elämästä. Kun Joonas (Antti Koivula) toteuttaa pitkäaikaisen haaveensa ja ryhtyy baarimikoksi avaamalla tangobaarin, on ystävillä paikka, missä kokoontua ja käydä läpi elämäntilanteitaan. ”Baarimikko ei avaudu, baarimikolle avaudutaan” toteaa Krisse (Tiina Räsänen). Elämänmakuinen tarina kertoo viiden ystävän vaiheista rakkauden, sydänsurujen ja ystävyyden myllerryksessä. Mitä tapahtuu, kun Benkku (Aki Samuli) yrittää pokata tangolla tai kun Jossu (Heta Halonen) tekee bänät tekstarilla ja onko Jusa (Petri Hervanto) päässyt yli omasta tragediastaan?

Ammattitanssijoina esityksessä ovat Mikko ja Carina Ahti sekä Nina Krook ja Alejandro Marce Herlan. Mikko Ahti on tullut tutuksi Tanssii Tähtien Kanssa tv-ohjelmasta sekä eri teatteriproduktioista. Carina Ahti on tanssinut miehensä Mikon kanssa pitkän kilpauran ja he opettavat yhdessä esiintymisten lisäksi. Nina Krook on argentinalaisen tangon ammattilainen parinsa Alejandro Marce Herlanin kanssa.

”Tango on vahva osa suomalaista kulttuuria ja identiteettiä. Suomalaisilla on suorastaan intohimo tangoon niin laulaen, tanssien kuin soittaen” kertoo Tangokuninkaalliset ry puheenjohtaja Aki Samuli. ” Me Tangokuninkaalliset yhdistimme voimamme ja perustimme 2019 oman yhdistyksen Tanku Ry (Tangokuninkaalliset Ry) jonka päätavoitteena on ylläpitää, elävöittää ja kehittää sekä suojella tangomusiikkia. On mahtavaa, että neljä kruunattua tangolähettilästä on valittu ”Mahdoton rakkaus” tuotantoon” jatkaa Aki.

”Tangomusiikki herättää meissä suomalaisissa suuria tunteita. On upeaa päästä tekemään näyttämölle tangoon keskittyvä kokonaisuus” kertoo esityksen ohjaaja Sari Siikander. ”Musiikki on tarinallisesti suuressa roolissa tässä esityksessä” Sari lisää.

”Tarinassa laulu, tanssi ja musiikki yhdistyvät roolihenkilöihin aivan uudella tavalla ja vie tangon sellaiselle tasolle, jossa sitä ei ole koskaan Suomessa nähty eikä koettu. Näytös sopii kaikille ja erityisesti niille, joille tango musiikkina on vielä vieras” iloitsee Tanku ry:n puheenjohtaja ja tangokuningas Aki Samuli. ” Suomalaista tangoa voivat esittää kaikki ihmiset: miehet ja naiset, nuoret ja ikäihmiset. Ketään ei syrjitä. Tango yhdistää ja luo muistoja kerrottavaksi sukupolvilta aina toisille” hän jatkaa.

Esityksen ensi-ilta on 21.9.2023 Kulttuurikeskus Martinuksessa Vantaalla. Katso esityspäivät ja -paikat www.mahdotonrakkaus.fi ja ota sometilit seurantaan FB/IG @mahdotonrakkaus

Antti Koivula – Joonas – Baarin omistaja
Aki Samuli – Benkku - Sähköasentaja
Heta Halonen – Jossu - Musiikkiopettaja
Petri Hervanto – Jusa - koodaaja
Tiina Räsänen – Krisse – Personal trainer

Tanssijat:
Mikko Ahti
Carina Ahti
Nina Krook
Alejandro Marce Herlan.

Ohjaus: Sari Siikander
Käsikirjoitus: Taina West
Musiikin sovitus: Jasse Varpama
Puvustus: Helena Ahti-Hallberg
Lavastus: Elevent Group Oy

Ikäraja: S

Kesto n. 2 h, sisältää väliajan

", + "sv": null, + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": null, + "fi": "Tangonäytelmä Mahdoton Rakkaus on esitys, joka nostaa esille uutta kotimaista tangomusiikkia unohtamatta genren kuolemattomia klassikoita. Ohjauksesta vastaa Sari Siikander, käsikirjoituksesta Taina West ja musiikin sovituksista Jasse Varpama. Tuotanto Elevent Group Oy.", + "sv": null, + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-13T17:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": { + "en": null, + "fi": "Mocked provider", + "sv": null, + "__typename": "LocalizedObject" + }, + "infoUrl": { + "en": null, + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/FA4DFCEDF7BD52C6E246FE0B32F5BC89/Mahdoton_rakkaus", + "sv": null, + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "kulke:60997", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:60997/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "96968", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_730886.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:54", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:54/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Ruotsi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:55", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:55/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Englanti", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:8740", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Malmi", + "sv": "Malm", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Ala-Malmi", + "sv": "Nedre Malm", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Malmi", + "sv": "Malm", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:8740/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Malmitalo", + "fi": "Malmitalo", + "sv": "Malms kulturhus", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Ala-Malmin tori 1", + "fi": "Ala-Malmin tori 1", + "sv": "Nedre Malms torg 1", + "__typename": "LocalizedObject" + }, + "postalCode": "00700", + "position": { + "coordinates": [25.01497, 60.250507], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 9 310 80831", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": true, + "price": null, + "description": null, + "infoUrl": null, + "__typename": "Offer" + } + ], + "name": { + "en": "Sing-alongs at Malmitalo", + "fi": "Malmitalon yhteislaulut", + "sv": "Allsång på Malms kulturhus", + "__typename": "LocalizedObject" + }, + "description": { + "en": "

Sing-alongs at Malmitalo – best Tuesday of the month!

Led by Jukka Okkonen and Pauli Kainulainen, you can once again sing your heart out in Malmisali!

Spring sing-alongs are held in Malmisali on 12 September, 17 October, 14 November and 19 December at 17.00.

We look forward to seeing you!

", + "fi": "

Malmitalon yhteislaulut – kuukauden paras tiistai!

Jukka Okkosen ja Pauli Kainulaisen johdolla saa Malmisalissa taas laulaa ihan sydämensä kyllyydestä!

Syksyn yhteislaulut järjestetään 12.9., 17.10., 14.11. sekä 19.12. klo 17.00 Malmisalissa. Tervetuloa!

", + "sv": "

Allsång på Malms kulturhus - den bästa tisdagen i månaden!

Nu får publiken åter sjunga för full hals i Malmsalen under ledning av Jukka Okkonen och Pauli Kainulainen!

Vårens allsång ordnas 12.9, 17.10, 14.11 samt 19.12 kl. 17.00 i Malmsalen.

Välkommen!

", + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "Sing-alongs at Malmitalo – best Tuesday of the month!", + "fi": "Malmitalon yhteislaulut – kuukauden paras tiistai!", + "sv": "Allsång på Malms kulturhus - den bästa tisdagen i månaden!", + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-14T15:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/en/events/event/250E39CE114678168B01EAE01225D7E9/Sing-alongs_at_Malmitalo", + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/250E39CE114678168B01EAE01225D7E9/Malmitalon_yhteislaulut", + "sv": "http://mocked-test-server.fi/sv/evenemang/event/250E39CE114678168B01EAE01225D7E9/Allsang_pa_Malms_kulturhus", + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "kulke:59586", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:59586/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "91109", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_729007.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:348", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:348/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:49", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:49/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "teatteri", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:54", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:54/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Ruotsi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:55", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:55/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Englanti", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:7258", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Ullanlinna", + "sv": "Ulrikasborg", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Kaartinkaupunki", + "sv": "Gardesstaden", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Kaartinkaupunki", + "sv": "Gardesstaden", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:7258/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Theatre", + "fi": "teatteri", + "sv": "teatern", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Kasarmikatu 46-48", + "fi": "Kasarmikatu 46-48", + "sv": "Kaserngatan 46-48", + "__typename": "LocalizedObject" + }, + "postalCode": "00130", + "position": { + "coordinates": [24.947306, 60.16663], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 9 310 36563", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": false, + "price": { + "en": "31,50 €", + "fi": "31,50 €", + "sv": "31,50 €", + "__typename": "LocalizedObject" + }, + "description": null, + "infoUrl": { + "en": "https://mocked-ticket-service.fi/eventseries/name-3356547", + "fi": "https://mocked-ticket-service.fi/eventseries/name-3356547", + "sv": "https://mocked-ticket-service.fi/eventseries/name-3356547", + "__typename": "LocalizedObject" + }, + "__typename": "Offer" + } + ], + "name": { + "en": "Murcof x Sergi Palau + Steve Hauschildt", + "fi": "Murcof x Sergi Palau + Steve Hauschildt", + "sv": "Murcof x Sergi Palau + Steve Hauschildt", + "__typename": "LocalizedObject" + }, + "description": { + "en": "

Audiences will be able to experience and enjoy the immersive piece created jointly by master of minimalist electronic music Murcof and visual artist Sergi Palau at Savoy Theatre in Helsinki late in the year. The concert on Tuesday 14 November will also feature the performance of another veteran of electronic music, Steve Hauschildt.

Fernando Corona, a.k.a. Murcof, who draws influences from ambient, minimalist techno, industrial and classical music, has been making music since the late 1980s, playing with numerous rock and jazz bands. The Mexican-born Corona’s electronic project Murcof began at the turn of the millennium with him sampling contemporary classical music for his electronic sounds. Murcof’s latest studio album, which he created in cooperation with Alias Dance Company, is the spring 2021 release The Alias Sessions.

Sergi Palau, the man responsible for the concert’s visual presentation, is known as the founder of the Niño Viejo art collective. Palau, who is also a member of the visual creation laboratory Radiante and the artistic director of the VOlumens festival, has been a VJ at numerous festivals and worked with many musicians, such as Felix Da Housecat, Roni Size and Richie Hawtin.

The second performer of the night, the American artist Steve Hauschildt, is also one of the leading creators of electronic music, who is also known for his band Emeralds. Hauschildt creates his music using synthesizers, computers and digital processing, aiming to continuously develop his musical expression. Hauschildt’s widely acclaimed sixth studio album Nonlin was released in August 2018.

MURCOF x Sergi Palau (MX)
STEVE HAUSCHILDT (US)
Tue 14 November 2023 Helsinki, Savoy Theatre

Evening schedule:
18:00 Doors
19:00 STEVE HAUSCHILDT
20:15 MURCOF x SERGI PALAU

The stalls form a designated alcohol serving area for adults age 18 and older. The balcony is for people of all ages, no alcohol served.

TICKETS: In advance, from €31.50 + order fees (from €1.50 mocked-ticket-service.fi)
At the door €36.50, if not sold out.

", + "fi": "

Minimalistisen elektronisen musiikin taituri Murcofin ja visuaalisena taiteilijana tunnetun Sergi Palaun ainutlaatuinen immersiivinen yhteisteos nähdään Helsingin Savoy-teatterissa loppuvuodesta. Tiistaina 14. marraskuuta toteutuvan konsertti-illan täydentää toinen pitkän linjan elektronisen musiikin tekijä Steve Hauschildt.

Ennakkoluulottomasti muun muassa ambientista, minimalistisesta teknosta, industrialista ja klassisesta musiikista vaikutteita ammentava Murcof eli Fernando Corona on tehnyt musiikkia 80-luvun lopusta lähtien soittaen lukuisissa rock- ja jazzbändeissä. Meksikolaissyntyisen Coronan elektroninen projekti Murcof käynnistyi vuosituhannen alussa, kun hän aloitti samplaamaan modernia klassista musiikkia elektronisiin soundeihin. Murcofin viimeisin studioalbumi on yhteistyössä Alias Dance Companyn kanssa syntynyt ja keväällä 2021 julkaistu ”The Alias Sessions”.

Konsertin visuaalisesta ilmeestä vastaava Sergi Palau tunnetaan Niño Viejotaidekollektiivin perustajana. Myös visuaalisen luomisen laboratorion Radianten jäsen ja VOlumens-festivaalin taiteellinen johtaja Palau on toiminut VJ:nä lukuisilla festivaaleilla ja työskennellyt monien muusikoiden kuten Felix Da Housecatin, Roni Sizen ja Richie Hawtinin kanssa.

Illan toinen artisti on niinikään modernin elektronisen musiikin eturivin tekijöihin lukeutuva, myös Emeralds-yhtyeestä tunnettu yhdysvaltalainen Steve Hauschildt. Hauschildt hyödyntää musiikissaan syntetisaattoreita, tietokoneita ja digitaalista prosessointia kehittäen jatkuvasti omaa musiikillista muotokieltään. Hauschildtin ylistetty kuudes studioalbumi ”Nonlin” ilmestyi elokuussa 2018.

MURCOF x Sergi Palau (MX)
STEVE HAUSCHILDT (US)
Ti 14.11.2023 Helsinki, Savoy-teatteri

Illan aikataulu:
18:00 Ovet
19:00 STEVE HAUSCHILDT
20:15 MURCOF x SERGI PALAU

Permanto K18 anniskelualue. Parveke S, ei anniskelua

LIPUT: Ennakkoon alk. 31,50 EUR + tilausmaksut (alk. 1,50 € mocked-ticket-service.fi)
Ovelta 36,50 EUR, mikäli esitys ei ole loppuunmyyty.

", + "sv": "

Begåvningen inom minimalistisk elektronisk musik Murcofs och den visuella konstnären Sergi Palaus unika immersiva gemensamma verk ses på Savoyteatern i Helsingfors i slutet av året. Konsertkvällen som går av stapeln tisdagen den 14 november kompletteras av en annan artist med en lång meritförteckning inom elektronisk musik, Steve Hauschildt.

Murcof alias Fernando Corona, som fördomsfritt hämtar influenser från bland annat ambientmusik, minimalistisk tekno, industriell och klassisk musik har skapat musik sedan sent 80-tal och spelat i flera rock- och jazzband. Mexikanska Coronas elektroniska projekt Murcof startade i början av millenniet när han började sampla modern klassisk musik med elektroniska sound. Murcofs senaste studioalbum The Alias Sessions, som skapades i samarbete med Alias Dance Company, kom ut våren 2021.

Sergi Palau, mannen som skapat konsertens visuella uttryck, är känd som grundaren av konstkollektivet Niño Viejo. Palau, som också är medlem i laboratoriet Radiante för visuellt skapande och konstnärlig ledare för festivalen VOlumens har varit VJ på många festivaler och arbetat med ett stort antal musiker, till exempel Felix Da Housecat, Roni Size och Richie Hawtin.

Kvällens andra artist Steve Hauschildt (USA) är likaså en av de främsta namnen inom modern elektronisk musik och även känd från bandet Emeralds. I sin musik utnyttjar Hauschildt syntetisatorer, datorer och digital bearbetning och utvecklar ständigt sitt musikaliska formspråk. Hauschildts lovordade sjätte studioalbum Nonlin kom ut i augusti 2018.

MURCOF x Sergi Palau (MX)
STEVE HAUSCHILDT (US)
Tis. 14.11.2023 Helsingfors, Savoyteatern

Kvällens schema:
18:00 Doors
19:00 STEVE HAUSCHILDT
20:15 MURCOF x SERGI PALAU

Parkett utskänkningsområde, 18-årsgräns Läktare ingen utskänkning eller åldersgräns

BILJETTER: I förköp från 31,50 EUR + beställningsavgift (från 1,50 € mocked-ticket-service.fi)
Vid dörren 36,50 EUR, om spelningen inte är slutsåld.

", + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "Audiences will be able to experience and enjoy the immersive piece created jointly by master of minimalist electronic music Murcof and visual artist Sergi Palau at Savoy Theatre in Helsinki late in the year. The concert on Tuesday 14 November will also feature the performance of another veteran of electronic music, Steve Hauschildt.", + "fi": "Minimalistisen elektronisen musiikin taituri Murcofin ja visuaalisena taiteilijana tunnetun Sergi Palaun ainutlaatuinen immersiivinen yhteisteos nähdään Helsingin Savoy-teatterissa loppuvuodesta. Tiistaina 14. marraskuuta toteutuvan konsertti-illan täydentää toinen pitkän linjan elektronisen musiikin tekijä Steve Hauschildt.", + "sv": "Begåvningen inom minimalistisk elektronisk musik Murcofs och den visuella konstnären Sergi Palaus unika immersiva gemensamma verk ses på Savoyteatern i Helsingfors i slutet av året. Konsertkvällen som går av stapeln tisdagen den 14 november kompletteras av en annan artist med en lång meritförteckning inom elektronisk musik, Steve Hauschildt.", + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-14T17:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": { + "en": "Mocked provider", + "fi": "Mocked provider", + "sv": "Mocked provider", + "__typename": "LocalizedObject" + }, + "infoUrl": { + "en": "http://mocked-test-server.fi/en/events/event/94527E83247F2C90F2A7C93C29417D4A/Murcof_x_Sergi_Palau_Steve_Hauschildt", + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/94527E83247F2C90F2A7C93C29417D4A/Murcof_x_Sergi_Palau_Steve_Hauschildt", + "sv": "http://mocked-test-server.fi/sv/evenemang/event/94527E83247F2C90F2A7C93C29417D4A/Murcof_x_Sergi_Palau_Steve_Hauschildt", + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "helsinki:ageujtsxuy", + "internalId": "https://api.hel.fi/linkedevents/v1/event/helsinki:ageujtsxuy/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventScheduled", + "externalLinks": [], + "images": [ + { + "id": "77040", + "name": "Musiikkitalo", + "url": "https://api.hel.fi/linkedevents/media/images/20140507_0814_L1002723_4110_xdjRvKO.jpg", + "photographerName": "Helsinki Partners (c) Jussi Hellsten", + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": { + "internalId": "https://api.hel.fi/linkedevents/v1/event/helsinki:ageujts2t4/", + "__typename": "InternalIdObject" + }, + "inLanguage": [], + "keywords": [ + { + "id": "yso:p11185", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p11185/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "concerts", + "fi": "konsertit", + "sv": "konserter (framträdanden)", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1304", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1304/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "festivals", + "fi": "festivaalit", + "sv": "festivaler", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p18434", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p18434/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "art music", + "fi": "taidemusiikki", + "sv": "konstmusik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:20633", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Vironniemi", + "sv": "Estnäs", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Kluuvi", + "sv": "Gloet", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Kluuvi", + "sv": "Gloet", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:20633/", + "email": null, + "infoUrl": { + "en": "https://mocked-test-server.fi/en/", + "fi": "https://mocked-test-server.fi/", + "sv": "https://mocked-test-server.fi/sv/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Musiikkitalo - Helsinki Music Centre", + "fi": "Musiikkitalo", + "sv": "Musikhuset", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Mannerheimintie 13a", + "fi": "Mannerheimintie 13a", + "sv": "Mannerheimvägen 13a", + "__typename": "LocalizedObject" + }, + "postalCode": "00100", + "position": { + "coordinates": [24.935074, 60.1737], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 20 707 0400", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": false, + "price": { + "en": "5-40€", + "fi": "5-40€", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": { + "en": "", + "fi": "", + "sv": null, + "__typename": "LocalizedObject" + }, + "infoUrl": { + "en": "https://mocked-test-server/aihe/rso-in-english/concerts-season-2023-2024", + "fi": "https://mocked-test-server/aihe/rso/konsertit-kausi-2023-2024", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Offer" + } + ], + "name": { + "en": "Orchestra Festival", + "fi": "Orkesterifestivaali", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": { + "en": "

description

", + "fi": "

description

", + "sv": null, + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "Orchestra Festival", + "fi": "Orkesteri festivaali", + "sv": null, + "__typename": "LocalizedObject" + }, + "endTime": "2023-11-15T19:00:00Z", + "startTime": "2023-11-15T17:00:00Z", + "publisher": "ytj:0586977-6", + "provider": { + "en": "Mocked provider", + "fi": "Mocked provider", + "sv": null, + "__typename": "LocalizedObject" + }, + "infoUrl": { + "en": "https://mocked-test-server/aihe/rso-in-english/concerts-season-2023-2024", + "fi": "https://mocked-test-server/aihe/rso/konsertit-kausi-2023-2024", + "sv": null, + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": { + "en": "Concert Hall, Paavo Hall", + "fi": "konserttisali, Paavo-sali", + "sv": null, + "__typename": "LocalizedObject" + }, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "kulke:61162", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:61162/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "97932", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_738079.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:47", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:47/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Caisa", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:54", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:54/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Ruotsi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:55", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:55/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Englanti", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:596", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:596/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Muu", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:733", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:733/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Luennot ja keskustelut", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p14004", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p14004/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "conversation", + "fi": "keskustelu", + "sv": "samtal", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p15875", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p15875/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "lectures", + "fi": "luennot", + "sv": "föreläsningar", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:7256", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Kallio", + "sv": "Berghäll", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Vilhonvuori", + "sv": "Vilhemsberg", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Sörnäinen", + "sv": "Sörnäs", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:7256/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Cultural Centre Caisa", + "fi": "Caisa", + "sv": "Caisa", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Kaikukatu 4, Helsinki", + "fi": "Kaikukatu 4, Helsinki", + "sv": "Ekogatan 4, Helsinki", + "__typename": "LocalizedObject" + }, + "postalCode": "00530", + "position": { + "coordinates": [24.960548, 60.182697], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 0 123 12312", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": true, + "price": null, + "description": null, + "infoUrl": null, + "__typename": "Offer" + } + ], + "name": { + "en": "Global Club Nights", + "fi": "Global Club Nights", + "sv": "Global Club Nights", + "__typename": "LocalizedObject" + }, + "description": { + "en": "

Musicians

", + "fi": "

Muusikot

", + "sv": "

Musikerna

", + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "Musicians", + "fi": "Muusikot", + "sv": "Musikerna", + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-15T13:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/en/events/event/76B406523E7B0D29BCB1EFCFCD2786D9", + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/76B406523E7B0D29BCB1EFCFCD2786D9", + "sv": "http://mocked-test-server.fi/sv/evenemang/event/76B406523E7B0D29BCB1EFCFCD2786D9", + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "kulke:60124", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:60124/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "93919", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_733071.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:44", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:44/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Stoa", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:54", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:54/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Ruotsi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:55", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:55/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Englanti", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:596", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:596/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Muu", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:732", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:732/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Työpajat", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p39924", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p39924/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "workshops (social inclusion)", + "fi": "työpajatoiminta", + "sv": "verkstadsverksamhet", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:7259", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Vartiokylä", + "sv": "Botby", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Itäkeskus", + "sv": "Östra centrum", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Vartiokylä", + "sv": "Botby", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:7259/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Stoa", + "fi": "Stoa", + "sv": "Stoa", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Turunlinnantie 1", + "fi": "Turunlinnantie 1", + "sv": "Åbohusvägen 1", + "__typename": "LocalizedObject" + }, + "postalCode": "00900", + "position": { + "coordinates": [25.07989, 60.212097], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 9 310 88405", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": true, + "price": null, + "description": null, + "infoUrl": null, + "__typename": "Offer" + } + ], + "name": { + "en": "Choir", + "fi": "Kuoro", + "sv": "Kör", + "__typename": "LocalizedObject" + }, + "description": { + "en": "

Would you like to learn Finnish by singing in Finnish?

", + "fi": "

Haluatko opetella laulamaan suomeksi, suomalaisia ja kansainvälisiä lauluja yhdessä muiden kanssa?

", + "sv": "

Vill du lära dig sjunga finländska och internationella sånger på finska tillsammans med andra?

", + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "Would you like to learn Finnish by singing in Finnish?", + "fi": "Haluatko opetella laulamaan suomeksi, suomalaisia ja kansainvälisiä lauluja yhdessä muiden kanssa?", + "sv": "Vill du lära dig sjunga finländska och internationella sånger på finska tillsammans med andra?", + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-15T16:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/en/events/event/A73124ED64CA6F2CABD89885905F92B4", + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/A73124ED64CA6F2CABD89885905F92B4", + "sv": "http://mocked-test-server.fi/sv/evenemang/event/A73124ED64CA6F2CABD89885905F92B4", + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "helsinki:ageujtsx34", + "internalId": "https://api.hel.fi/linkedevents/v1/event/helsinki:ageujtsx34/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventScheduled", + "externalLinks": [], + "images": [ + { + "id": "77040", + "name": "Musiikkitalo", + "url": "https://api.hel.fi/linkedevents/media/images/20140507_0814_L1002723_4110_xdjRvKO.jpg", + "photographerName": "Helsinki Partners (c) Jussi Hellsten", + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": { + "internalId": "https://api.hel.fi/linkedevents/v1/event/helsinki:ageujts2t4/", + "__typename": "InternalIdObject" + }, + "inLanguage": [], + "keywords": [ + { + "id": "yso:p11185", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p11185/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "concerts", + "fi": "konsertit", + "sv": "konserter (framträdanden)", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1304", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1304/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "festivals", + "fi": "festivaalit", + "sv": "festivaler", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p18434", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p18434/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "art music", + "fi": "taidemusiikki", + "sv": "konstmusik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:20633", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Vironniemi", + "sv": "Estnäs", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Kluuvi", + "sv": "Gloet", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Kluuvi", + "sv": "Gloet", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:20633/", + "email": null, + "infoUrl": { + "en": "https://mocked-test-server.fi/en/", + "fi": "https://mocked-test-server.fi/", + "sv": "https://mocked-test-server.fi/sv/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Musiikkitalo - Helsinki Music Centre", + "fi": "Musiikkitalo", + "sv": "Musikhuset", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Mannerheimintie 13a", + "fi": "Mannerheimintie 13a", + "sv": "Mannerheimvägen 13a", + "__typename": "LocalizedObject" + }, + "postalCode": "00100", + "position": { + "coordinates": [24.935074, 60.1737], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 20 707 0400", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": false, + "price": { + "en": "5-40€", + "fi": "5-40€", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": { + "en": "", + "fi": "", + "sv": null, + "__typename": "LocalizedObject" + }, + "infoUrl": { + "en": "https://mocked-test-server/aihe/rso-in-english/concerts-season-2023-2024", + "fi": "https://mocked-test-server/aihe/rso/konsertit-kausi-2023-2024", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Offer" + } + ], + "name": { + "en": "Orchestra Festival", + "fi": "Orkesteri festivaali", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": { + "en": "

Description

", + "fi": "

Kuvaus

", + "sv": null, + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "Description", + "fi": "Kuvaus.", + "sv": null, + "__typename": "LocalizedObject" + }, + "endTime": "2023-11-16T19:00:00Z", + "startTime": "2023-11-16T17:00:00Z", + "publisher": "ytj:0586977-6", + "provider": { + "en": "Mocked provider", + "fi": "Mocked provider", + "sv": null, + "__typename": "LocalizedObject" + }, + "infoUrl": { + "en": "https://mocked-test-server.fi/aihe/rso-in-english/concerts-season-2023-2024", + "fi": "https://mocked-test-server.fi/aihe/rso/konsertit-kausi-2023-2024", + "sv": null, + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": { + "en": "Concert Hall, Paavo Hall", + "fi": "konserttisali, Paavo-sali", + "sv": null, + "__typename": "LocalizedObject" + }, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "kulke:60113", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:60113/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "93920", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_733048.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:348", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:348/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:44", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:44/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Stoa", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:732", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:732/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Työpajat", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p39924", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p39924/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "workshops (social inclusion)", + "fi": "työpajatoiminta", + "sv": "verkstadsverksamhet", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:7259", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Vartiokylä", + "sv": "Botby", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Itäkeskus", + "sv": "Östra centrum", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Vartiokylä", + "sv": "Botby", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:7259/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Stoa", + "fi": "Stoa", + "sv": "Stoa", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Turunlinnantie 1", + "fi": "Turunlinnantie 1", + "sv": "Åbohusvägen 1", + "__typename": "LocalizedObject" + }, + "postalCode": "00900", + "position": { + "coordinates": [25.07989, 60.212097], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 9 310 88405", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": true, + "price": null, + "description": null, + "infoUrl": null, + "__typename": "Offer" + } + ], + "name": { + "en": null, + "fi": "Opi suomea laulaen – Laulupajat maahanmuuttaneille", + "sv": null, + "__typename": "LocalizedObject" + }, + "description": { + "en": null, + "fi": "

Oletko maahanmuuttanut, joka haluaa opiskella suomea? Tule kokeilemaan hauskaa tapaa, joka huomioi musiikin monet mahdollisuudet vahvistaa suomen kielen oppimista.

Tilaisuus on aikuisille. Pääset laulamaan ja liikkumaan musiikin mukana yhdessä muiden kanssa ja samalla opit suomen kielen ääntämistä ja uusia sanoja. Tule mukaan laulamaan, vaikka osaisit vasta vähän suomea!

Kielenopiskelu laulaen on kotoutumiskoulutuksissa vuosien aikana kehitetty uusi toimintamalli. MuM Johanna Lehtinen-Schnabel on kehittänyt toimintamallin ja tutkii sitä edelleen. Toiminta huomioi vahvasti taiteen ja musiikin voimauttavan vaikutuksen tukien oppijan kokonaisvaltaista ilmaisua.

Kesto n. 80 min
Ryhmään mukaan on ilmoittauduttava etukäteen.
Kysy lisää ja ilmoittaudu: sanna.nuutinen@hel.fi

Syksyn laulupajakerrat:
to 7.9. klo 10 & 11.45
to 5.10. klo 10 ja 11.45
to 16.11. klo 10 & 11.45
torstai joulukuussa

", + "sv": null, + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": null, + "fi": "Oletko maahanmuuttanut, joka haluaa opiskella suomea? Tule kokeilemaan hauskaa tapaa, joka huomioi musiikin monet mahdollisuudet vahvistaa suomen kielen oppimista.", + "sv": null, + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-16T08:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": null, + "infoUrl": { + "en": null, + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/C0759879CC0D2C4D2208B91FF86CC3B4/Opi_suomea_laulaen_", + "sv": null, + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + }, + { + "id": "kulke:61054", + "internalId": "https://api.hel.fi/linkedevents/v1/event/kulke:61054/", + "audienceMinAge": null, + "audienceMaxAge": null, + "eventStatus": "EventRescheduled", + "externalLinks": [], + "images": [ + { + "id": "96971", + "name": "", + "url": "http://mocked-test-server.fi/instancedata/prime_product_resurssivaraus/kulke/embeds/EventPic_734797.jpg", + "photographerName": null, + "__typename": "EventImage" + } + ], + "subEvents": [], + "typeId": "General", + "superEvent": null, + "inLanguage": [], + "keywords": [ + { + "id": "kulke:31", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:31/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Musiikki", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:45", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:45/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Vuotalo", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:53", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:53/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Suomi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:54", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:54/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Ruotsi", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "kulke:55", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/kulke:55/", + "dataSource": "kulke", + "hasUpcomingEvents": true, + "name": { + "en": null, + "fi": "Englanti", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + }, + { + "id": "yso:p1808", + "internalId": "https://api.hel.fi/linkedevents/v1/keyword/yso:p1808/", + "dataSource": "yso", + "hasUpcomingEvents": true, + "name": { + "en": "music", + "fi": "musiikki", + "sv": "musik", + "__typename": "LocalizedObject" + }, + "__typename": "Keyword" + } + ], + "location": { + "id": "tprek:7260", + "divisions": [ + { + "type": "muni", + "name": { + "en": null, + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "district", + "name": { + "en": null, + "fi": "Vuosaari", + "sv": "Nordsjö", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "sub_district", + "name": { + "en": null, + "fi": "Keski-Vuosaari", + "sv": "Mellersta Nordsjö", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + }, + { + "type": "neighborhood", + "name": { + "en": null, + "fi": "Vuosaari", + "sv": "Nordsjö", + "__typename": "LocalizedObject" + }, + "__typename": "Division" + } + ], + "hasUpcomingEvents": true, + "internalId": "https://api.hel.fi/linkedevents/v1/place/tprek:7260/", + "email": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/", + "fi": "http://mocked-test-server.fi/", + "sv": "http://mocked-test-server.fi/", + "__typename": "LocalizedObject" + }, + "name": { + "en": "Vuosaari House", + "fi": "Vuotalo", + "sv": "Nordhuset", + "__typename": "LocalizedObject" + }, + "addressLocality": { + "en": "Helsinki", + "fi": "Helsinki", + "sv": "Helsingfors", + "__typename": "LocalizedObject" + }, + "streetAddress": { + "en": "Mosaiikkitori 2", + "fi": "Mosaiikkitori 2", + "sv": "Mosaiktorget 2", + "__typename": "LocalizedObject" + }, + "postalCode": "00980", + "position": { + "coordinates": [25.143385, 60.208565], + "__typename": "PlacePosition" + }, + "telephone": { + "en": null, + "fi": "+358 9 310 88802", + "sv": null, + "__typename": "LocalizedObject" + }, + "__typename": "Place" + }, + "offers": [ + { + "isFree": false, + "price": { + "en": "24 €", + "fi": "24 €", + "sv": "24 €", + "__typename": "LocalizedObject" + }, + "description": null, + "infoUrl": { + "en": "https://mocked-ticket-service.fi/artist/jiri-nikkinen-the-beatles-tribute-band/jiri-nikkinen-the-beatles-tribute-band-3477797", + "fi": "https://mocked-ticket-service.fi/artist/jiri-nikkinen-the-beatles-tribute-band/jiri-nikkinen-the-beatles-tribute-band-3477797", + "sv": "https://mocked-ticket-service.fi/artist/jiri-nikkinen-the-beatles-tribute-band/jiri-nikkinen-the-beatles-tribute-band-3477797", + "__typename": "LocalizedObject" + }, + "__typename": "Offer" + } + ], + "name": { + "en": "The Beatles Tribute Band: A Hard Day’s Night & Beatles For Sale album concert", + "fi": "the Beatles Tribute Band - A Hard Day's Night / Beatles For Sale - albumikonsertti", + "sv": "The Beatles Tribute Band: Albumkonserten A Hard Day’s Night & Beatles For Sale", + "__typename": "LocalizedObject" + }, + "description": { + "en": "

A testguy and his ensemble will make an early start to celebrate the two Beatles albums released in 1964, which will be 60 years old in 2024.

As usual, the musicians perform the songs in the proper album order, in the right key and with the right arrangements, with care and love for the Beatles.

You can no longer experience The Beatles, but you can experience this. Take a journey back in time to 1964, accompanied by the music of the world’s greatest pop group!

", + "fi": "

A testguy bändeineen ottaa varaslähdön vuonna 1964 julkaistuille kahdelle Beatles-albumille, jotka täyttävät 2024 peräti 60 vuotta.

Levyt julkaistiin Beatlemanian kuumimpaan aikaan ja A Hard Day’s Night oli ensimmäinen albumi, joka sisälsi pelkästään yhtyeen omaa tuotantoa. Kaikki biisit Lennon /McCartney.

Tutuun tapaan A testguy ja kumppanit esittävät kappaleet niiden oikeassa albumijärjestyksessä, oikeista sävellajeista ja oikein sovituksin, pieteetillä ja rakkaudesta Beatlesiin.

The Beatlesia et enää voi kokea, mutta tämän voit. Lähde aikamatkalle vuoteen 1964 maailman merkittävimmän pop-yhtyeen musiikin saattelemana!

", + "sv": "

A testguy och bandet tar en tjuvstart till två Beatlesalbum från 1964, som 2024 fyller redan 60 år.

På bekant vis framför A testguy och bandet låtarna i den rätta albumordningen, i rätt tonart och med rätt arrangemang, pietetsfullt och av kärlek till The Beatles.

The Beatles kan du inte längre uppleva, men detta kan du. Gör en tidsresa till år 1964 till tonerna av världens största popgrupp!

", + "__typename": "LocalizedObject" + }, + "shortDescription": { + "en": "A testguy and his ensemble will make an early start to celebrate the two Beatles albums released in 1964, which will be 60 years old in 2024.", + "fi": "A testguy bändeineen ottaa varaslähdön vuonna 1964 julkaistuille kahdelle Beatles-albumille, jotka täyttävät 2024 peräti 60 vuotta.", + "sv": "A testguy och bandet tar en tjuvstart till två Beatlesalbum från 1964, som 2024 fyller redan 60 år.", + "__typename": "LocalizedObject" + }, + "endTime": null, + "startTime": "2023-11-16T16:00:00Z", + "publisher": "ahjo:u4804001050", + "provider": null, + "infoUrl": { + "en": "http://mocked-test-server.fi/en/events/event/B96FD02572D78FFF78980573312AC0BA/Jiri_Nikkinen_The_Beatles_Tribute_Band_A_Hard_Day_s_Night_Beatles_For_Sale_album_concert", + "fi": "http://mocked-test-server.fi/fi/tapahtumat/event/B96FD02572D78FFF78980573312AC0BA/Jiri_Nikkinen_the_Beatles_Tribute_Band_-_A_Hard_Day_s_Night_Beatles_For_Sale_-_albumikonsertti", + "sv": "http://mocked-test-server.fi/sv/evenemang/event/B96FD02572D78FFF78980573312AC0BA/Jiri_Nikkinen_The_Beatles_Tribute_Band_Albumkonserten_A_Hard_Day_s_Night_Beatles_For_Sale", + "__typename": "LocalizedObject" + }, + "audience": [], + "locationExtraInfo": null, + "enrolmentStartTime": null, + "enrolmentEndTime": null, + "remainingAttendeeCapacity": null, + "__typename": "EventDetails" + } + ], + "__typename": "EventListResponse" + } +} From 4717ac9ab26fc433bf499e9dee2b4b0f7c74531e Mon Sep 17 00:00:00 2001 From: Niko Lindroos Date: Tue, 14 Nov 2023 10:14:17 +0200 Subject: [PATCH 3/3] chore: upgrade testing-library --- package.json | 6 +++--- yarn.lock | 27 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 849b0a9d..98941b3e 100644 --- a/package.json +++ b/package.json @@ -79,9 +79,9 @@ "@storybook/react": "^7.3.1", "@storybook/react-webpack5": "^7.3.1", "@storybook/testing-library": "^0.2.0", - "@testing-library/jest-dom": "^6.0.1", - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.0.0-beta", + "@testing-library/jest-dom": "^6.1.4", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.1", "@types/dompurify": "^3.0.2", "@types/jest": "^29.5.3", "@types/jest-axe": "^3.5.5", diff --git a/yarn.lock b/yarn.lock index 54be1a79..bef1b7f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@adobe/css-tools@^4.0.1": +"@adobe/css-tools@^4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28" integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg== @@ -3629,12 +3629,12 @@ lz-string "^1.5.0" pretty-format "^27.0.2" -"@testing-library/jest-dom@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.0.1.tgz#60c2aa05e0e3c07cbfaa319689e43227d95fa7c4" - integrity sha512-0hx/AWrJp8EKr8LmC5jrV3Lx8TZySH7McU1Ix2czBPQnLd458CefSEGjZy7w8kaBRA6LhoPkGjoZ3yqSs338IQ== +"@testing-library/jest-dom@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.1.4.tgz#cf0835c33bc5ef00befb9e672b1e3e6a710e30e3" + integrity sha512-wpoYrCYwSZ5/AxcrjLxJmCU6I5QAJXslEeSiMQqaWmP2Kzpd1LvF/qxmAIW2qposULGWq2gw30GgVNFLSc2Jnw== dependencies: - "@adobe/css-tools" "^4.0.1" + "@adobe/css-tools" "^4.3.1" "@babel/runtime" "^7.9.2" aria-query "^5.0.0" chalk "^3.0.0" @@ -3643,20 +3643,25 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.0.0.tgz#59030392a6792450b9ab8e67aea5f3cc18d6347c" - integrity sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg== +"@testing-library/react@^14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.1.0.tgz#01d64915111db99b50f8361d51d7217606805989" + integrity sha512-hcvfZEEyO0xQoZeHmUbuMs7APJCGELpilL7bY+BaJaMP57aWc6q1etFwScnoZDheYjk4ESdlzPdQ33IbsKAK/A== dependencies: "@babel/runtime" "^7.12.5" "@testing-library/dom" "^9.0.0" "@types/react-dom" "^18.0.0" -"@testing-library/user-event@^14.0.0", "@testing-library/user-event@^14.0.0-beta": +"@testing-library/user-event@^14.0.0": version "14.4.3" resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.4.3.tgz#af975e367743fa91989cd666666aec31a8f50591" integrity sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q== +"@testing-library/user-event@^14.5.1": + version "14.5.1" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.1.tgz#27337d72046d5236b32fd977edee3f74c71d332f" + integrity sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg== + "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"