Skip to content

Commit f3c5fc4

Browse files
authored
feat: minor tweaks to embed-components and embed-services (#1315)
1 parent 82ff8cf commit f3c5fc4

File tree

12 files changed

+139
-66
lines changed

12 files changed

+139
-66
lines changed

packages/embed-components/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"homepage": "https://github.com/looker-open-source/sdk-codegen/tree/master/packages/embed-components",
3636
"devDependencies": {
3737
"redux-saga-tester": "^1.0.874",
38-
"@looker/sdk-node": "^23.8.1",
38+
"@looker/sdk-node": "*",
3939
"@testing-library/react": "^11.2.7",
4040
"@looker/components-test-utils": "^1.5.27",
4141
"react-redux": "^7.2.9",
@@ -44,9 +44,10 @@
4444
},
4545
"dependencies": {
4646
"@looker/components": "^4.1.3",
47-
"@looker/embed-services": "23.8.1",
47+
"@looker/embed-services": "*",
4848
"@looker/redux": "^0.0.1",
49-
"@looker/sdk": "^23.8.1",
49+
"@looker/sdk": "*",
50+
"@looker/sdk-rtl": "*",
5051
"@reduxjs/toolkit": "^1.9.3",
5152
"@styled-icons/material-outlined": "^10.47.0",
5253
"react": "16.14.0",

packages/embed-components/src/QuickEmbed/QuickEmbed.spec.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ describe('QuickEmbed', () => {
7272
renderWithTheme(<QuickEmbed onClose={onClose} />)
7373

7474
expect(
75-
screen.getByRole('heading', { name: 'Get embed url' })
75+
screen.getByRole('heading', { name: 'Get embed URL' })
7676
).toBeInTheDocument()
7777
const textboxes = screen.getAllByRole('textbox')
7878

@@ -106,7 +106,7 @@ describe('QuickEmbed', () => {
106106
renderWithTheme(<QuickEmbed onClose={onClose} />)
107107

108108
expect(
109-
screen.getByRole('heading', { name: 'Get embed url' })
109+
screen.getByRole('heading', { name: 'Get embed URL' })
110110
).toBeInTheDocument()
111111

112112
expect(screen.queryByText(/Apply theme to/)).not.toBeInTheDocument()
@@ -127,7 +127,7 @@ describe('QuickEmbed', () => {
127127
renderWithTheme(<QuickEmbed onClose={onClose} />)
128128

129129
expect(
130-
screen.getByRole('heading', { name: 'Get embed url' })
130+
screen.getByRole('heading', { name: 'Get embed URL' })
131131
).toBeInTheDocument()
132132

133133
expect(screen.getByText('Apply theme to dashboard URL')).toBeInTheDocument()

packages/embed-components/src/QuickEmbed/QuickEmbed.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export const QuickEmbed = ({ onClose }: QuickEmbedProps) => {
7777
return (
7878
<Section padding="large">
7979
<Heading as="h3" fontWeight="medium">
80-
Get embed url
80+
Get embed URL
8181
</Heading>
8282

8383
<SpaceVertical pt="medium" pb="medium" gap="xsmall">

packages/embed-services/src/EmbedUrl.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,36 +37,41 @@ const THEMABLE_CONTENT: ContentType[] = [
3737
]
3838

3939
export interface IEmbedUrl {
40+
/** Current url */
4041
readonly url: string
42+
/** Path of the current page */
4143
readonly path: string
44+
/** Search string of the current url */
4245
readonly searchParams: Record<string, string>
46+
/** Determines whether the current URL is for a Dashboard */
4347
readonly isDashboard: boolean
48+
/** Determines whether the current URL is for an Explore */
4449
readonly isExplore: boolean
50+
/** Determines whether the current URl is for a Look */
4551
readonly isLook: boolean
52+
/** Type of content the URL represents */
4653
readonly contentType: ContentType
54+
/** Determines if current URL represents themable content */
4755
readonly isThemable: boolean
56+
/**
57+
* Builds the embed target url
58+
* @param includeSearchParams switch determining whether to include search params from target url
59+
* @param overrides any search key values to include in embed url e.g. 'k1=v1&k2=v2'
60+
*/
4861
embedUrl(includeSearchParams: boolean, overrides: Record<string, any>): string
4962
}
5063

5164
/**
5265
* A class for use when implementer requires components to be context aware
5366
*/
5467
export class EmbedUrl implements IEmbedUrl {
55-
/** Current url */
5668
private _url: URL
57-
/** Path of the current page */
5869
readonly path: string
59-
/** Search string of the current url */
6070
readonly searchParams: Record<string, string>
61-
/** Determines whether the current URL is for a Dashboard */
6271
readonly isDashboard: boolean
63-
/** Determines whether the current URL is for an Explore */
6472
readonly isExplore: boolean
65-
/** Determines whether the current URl is for a Look */
6673
readonly isLook: boolean
67-
/** Determines if current URL represents themable content */
6874
readonly isThemable: boolean
69-
/** Type of content the URL represents */
7075
readonly contentType: ContentType
7176
private readonly _embedUrl: string
7277

@@ -106,11 +111,6 @@ export class EmbedUrl implements IEmbedUrl {
106111
return type
107112
}
108113

109-
/**
110-
* Builds the embed target url
111-
* @param includeSearchParams switch determining whether to include search params from target url
112-
* @param overrides any search key values to include in embed url e.g. 'k1=v1&k2=v2'
113-
*/
114114
embedUrl(includeSearchParams = false, overrides: Record<string, any> = {}) {
115115
if (this.contentType === ContentType.Invalid) {
116116
throw new Error('Invalid content type')

packages/embed-services/src/ItemList.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ describe('ItemList', () => {
140140

141141
describe('getCacheDefault', () => {
142142
it('gets the default', () => {
143-
const actual = ItemList.getCacheDefault()
143+
let actual = ItemList.getCacheDefault()
144+
expect(actual).toBe(true)
145+
146+
actual = ItemList.getCacheDefault({ useCache: undefined })
144147
expect(actual).toBe(true)
145148
})
146149

packages/embed-services/src/ItemList.ts

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,31 @@ export interface GetOptions {
3737
export interface IItemList<T> {
3838
/** Cache time to live in seconds, defaults to 15 minutes */
3939
readonly timeToLive: number
40+
/** Cached items */
4041
items: T[]
42+
/** Expiration time */
4143
readonly expiresAt: number
44+
/** Creates an indexed collection from the cached items */
4245
index(key?: keyof T): ItemList<T>
46+
/** An indexed collection of items */
4347
indexedItems: Record<string, T>
48+
/** Determines if the cache has expired */
4449
expired(): boolean
50+
/** Computes the expiration time based on timeToLive */
4551
setExpiration(): void
52+
/** Ejects cache if expired */
4653
clearIfExpired(): void
54+
/**
55+
* Searches the collection for an item with the specified key/value pair
56+
* @param key or keys to search
57+
* @param expression to match
58+
*/
4759
find(key: keyof T | Array<keyof T>, value: any): T | undefined
60+
/**
61+
* Gets the cache option value if present, otherwise defaults to true
62+
* @param options to check
63+
*/
64+
getCacheDefault(options?: GetOptions): boolean
4865
}
4966

5067
export interface IEntityService<T> extends IItemList<T> {
@@ -58,11 +75,8 @@ export abstract class ItemList<T extends Record<string, any>>
5875
extends EntityService
5976
implements IItemList<T>
6077
{
61-
/** Cached items */
6278
items: T[] = []
63-
/** An indexed collection of items */
6479
indexedItems: Record<string, T> = {}
65-
/** Time when cache expires */
6680
expiresAt = 0
6781
/** Key to index by */
6882
private keyField = 'id'
@@ -71,9 +85,6 @@ export abstract class ItemList<T extends Record<string, any>>
7185
super(sdk, timeToLive)
7286
}
7387

74-
/**
75-
* Creates an indexed collection from the cached items
76-
*/
7788
index(key: keyof T = this.keyField) {
7889
this.keyField = key as string
7990
this.indexedItems = {}
@@ -85,33 +96,21 @@ export abstract class ItemList<T extends Record<string, any>>
8596
return this
8697
}
8798

88-
/** Computes the expiration time based on timeToLive */
8999
setExpiration() {
90100
this.expiresAt = Date.now() + this.timeToLive * 1000
91101
}
92102

93-
/**
94-
* Determines if the cache has expired
95-
*/
96103
expired() {
97104
return this.expiresAt <= Date.now()
98105
}
99106

100-
/**
101-
* Ejects cache if expired
102-
*/
103107
clearIfExpired() {
104108
if (this.expired()) {
105109
this.items = []
106110
this.indexedItems = {}
107111
}
108112
}
109113

110-
/**
111-
* Searches the collection for an item with the specified key/value pair
112-
* @param key or keys to search
113-
* @param expression to match
114-
*/
115114
find(key: keyof T | Array<keyof T>, expression: string): T | undefined {
116115
let result: T | undefined
117116
let keys: Array<keyof T>
@@ -122,9 +121,8 @@ export abstract class ItemList<T extends Record<string, any>>
122121
keys = key as Array<keyof T>
123122
}
124123

125-
let rx: RegExp
126124
try {
127-
rx = new RegExp(expression, 'i')
125+
const rx = new RegExp(expression, 'i')
128126

129127
for (const item of this.items) {
130128
for (const k of keys) {
@@ -141,12 +139,11 @@ export abstract class ItemList<T extends Record<string, any>>
141139
}
142140
}
143141

144-
/**
145-
* Gets the cache option value if present, otherwise defaults to true
146-
* @param options to check
147-
*/
148142
getCacheDefault(options?: GetOptions) {
149-
const cache = options && 'useCache' in options ? options.useCache : true
143+
const cache =
144+
options && 'useCache' in options && options.useCache !== undefined
145+
? options.useCache
146+
: true
150147
return cache
151148
}
152149
}

packages/embed-services/src/ServiceFactory.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
SOFTWARE.
2424
2525
*/
26-
import { Looker40SDK as LookerSDK } from '@looker/sdk'
26+
import { functionalSdk40 as funSdk } from '@looker/sdk'
2727
import type { IAPIMethods } from '@looker/sdk-rtl'
2828
import { session } from './test-utils'
2929
import { createFactory, destroyFactory, getFactory } from './ServiceFactory'
3030
import { getThemeService, registerThemeService } from './ThemeService'
3131

3232
describe('ServiceFactory', () => {
33-
const sdk: IAPIMethods = new LookerSDK(session)
33+
const sdk: IAPIMethods = funSdk(session)
3434

3535
afterEach(() => {
3636
destroyFactory()

packages/embed-services/src/ServiceFactory.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ import type { IAPIMethods } from '@looker/sdk-rtl'
2828
export type ServiceCreatorFunc<T> = (sdk: IAPIMethods, timeToLive?: number) => T
2929

3030
export interface IServiceFactory {
31+
/**
32+
* Retrieves a service
33+
* @param serviceName to retrieve
34+
*/
3135
get<T>(serviceName: string): T
36+
/**
37+
* Registers or creates a service
38+
* @param serviceName name of service.
39+
* @param serviceCreator function that creates the service.
40+
* @param timeToLive in seconds, for the service cache. Defaults to 15 minutes.
41+
*/
3242
register<T>(
3343
serviceName: string,
3444
serviceCreator: ServiceCreatorFunc<T>,
@@ -51,12 +61,6 @@ class ServiceFactory implements IServiceFactory {
5161
return service
5262
}
5363

54-
/**
55-
* Registers or creates a service
56-
* @param serviceName name of service.
57-
* @param serviceCreator function that creates the service.
58-
* @param timeToLive in seconds, for the service cache. Defaults to 15 minutes.
59-
*/
6064
register<T>(
6165
serviceName: string,
6266
serviceCreator: ServiceCreatorFunc<T>,

packages/embed-services/src/ThemeService.spec.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
2525
*/
2626
import {
27-
Looker40SDK as LookerSDK,
27+
functionalSdk40 as funSdk,
2828
all_themes,
2929
update_theme,
3030
create_theme,
@@ -38,11 +38,10 @@ import { themeServiceCreator } from './ThemeService'
3838
import type { IThemeService } from './ThemeService'
3939
import { TestConfig, session, timeout } from './test-utils'
4040

41-
const config = TestConfig()
42-
const themes = config.testData.themes
43-
4441
describe('ThemeService', () => {
45-
const sdk: IAPIMethods = new LookerSDK(session)
42+
const config = TestConfig()
43+
const themes = config.testData.themes
44+
const sdk: IAPIMethods = funSdk(session)
4645
let service: IThemeService
4746
let testThemes: ITheme[]
4847
const themeCount = themes.length + 1 // includes the Looker theme

packages/embed-services/src/ThemeService.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@ export interface IThemeService
4141
extends IItemList<ITheme>,
4242
IEntityService<ITheme> {
4343
defaultTheme?: ITheme
44+
/**
45+
* Gets the default theme
46+
* @param ts Timestamp representing the target datetime for the active period. Defaults to 'now'
47+
*/
4448
getDefaultTheme(ts?: Date, options?: GetOptions): Promise<ITheme>
49+
/**
50+
* Retrieves all themes and the default theme
51+
*/
4552
load(options?: GetOptions): Promise<IThemeService>
4653
}
4754

@@ -101,10 +108,6 @@ class ThemeService extends ItemList<ITheme> implements IThemeService {
101108
return theme
102109
}
103110

104-
/**
105-
* Gets the default theme
106-
* @param ts Timestamp representing the target datetime for the active period. Defaults to 'now'
107-
*/
108111
async getDefaultTheme(ts?: Date) {
109112
if (this.expired()) {
110113
this.defaultTheme = await this.sdk.ok(default_theme(this.sdk, ts))
@@ -123,9 +126,6 @@ class ThemeService extends ItemList<ITheme> implements IThemeService {
123126
this.index()
124127
}
125128

126-
/**
127-
* Retrieves all themes and the default theme
128-
*/
129129
async load(options?: GetOptions) {
130130
await this.getDefaultTheme()
131131
this.items = await this.sdk.ok(all_themes(this.sdk, options?.fields))

0 commit comments

Comments
 (0)