@teambit/component 0.0.1078 → 0.0.1080

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/component.ui.runtime.tsx +19 -9
  2. package/dist/component.d.ts +1 -1
  3. package/dist/component.graphql.d.ts +5 -2
  4. package/dist/component.graphql.js +4 -1
  5. package/dist/component.graphql.js.map +1 -1
  6. package/dist/component.ui.runtime.js +17 -9
  7. package/dist/component.ui.runtime.js.map +1 -1
  8. package/dist/get-component-opts.d.ts +1 -2
  9. package/dist/get-component-opts.js.map +1 -1
  10. package/dist/{preview-1686799133952.js → preview-1686971843539.js} +2 -2
  11. package/dist/ui/component.d.ts +1 -2
  12. package/dist/ui/component.js +24 -9
  13. package/dist/ui/component.js.map +1 -1
  14. package/dist/ui/index.d.ts +5 -2
  15. package/dist/ui/index.js +59 -9
  16. package/dist/ui/index.js.map +1 -1
  17. package/dist/ui/menu/index.d.ts +1 -1
  18. package/dist/ui/menu/index.js.map +1 -1
  19. package/dist/ui/menu/menu.d.ts +47 -8
  20. package/dist/ui/menu/menu.js +172 -84
  21. package/dist/ui/menu/menu.js.map +1 -1
  22. package/dist/ui/menu/nav-plugin.d.ts +12 -3
  23. package/dist/ui/menu/nav-plugin.js.map +1 -1
  24. package/dist/ui/use-component-logs.d.ts +16 -0
  25. package/dist/ui/use-component-logs.js +93 -0
  26. package/dist/ui/use-component-logs.js.map +1 -0
  27. package/dist/ui/use-component-query.d.ts +2 -86
  28. package/dist/ui/use-component-query.js +62 -188
  29. package/dist/ui/use-component-query.js.map +1 -1
  30. package/dist/ui/use-component.d.ts +3 -18
  31. package/dist/ui/use-component.fragments.d.ts +10 -0
  32. package/dist/ui/use-component.fragments.js +183 -0
  33. package/dist/ui/use-component.fragments.js.map +1 -0
  34. package/dist/ui/use-component.js +19 -0
  35. package/dist/ui/use-component.js.map +1 -1
  36. package/dist/ui/use-component.model.d.ts +40 -0
  37. package/dist/ui/use-component.model.js +3 -0
  38. package/dist/ui/use-component.model.js.map +1 -0
  39. package/dist/ui/use-component.utils.d.ts +1 -0
  40. package/dist/ui/use-component.utils.js +17 -0
  41. package/dist/ui/use-component.utils.js.map +1 -0
  42. package/package-tar/teambit-component-0.0.1080.tgz +0 -0
  43. package/package.json +22 -23
  44. package/ui/component.tsx +11 -5
  45. package/ui/index.ts +21 -2
  46. package/ui/menu/index.ts +7 -1
  47. package/ui/menu/menu.tsx +196 -68
  48. package/ui/menu/nav-plugin.tsx +14 -6
  49. package/ui/use-component-logs.ts +65 -0
  50. package/ui/use-component-query.ts +57 -160
  51. package/ui/use-component.fragments.ts +169 -0
  52. package/ui/use-component.model.ts +45 -0
  53. package/ui/use-component.tsx +4 -19
  54. package/ui/use-component.utils.ts +9 -0
  55. package/package-tar/teambit-component-0.0.1078.tgz +0 -0
package/ui/menu/menu.tsx CHANGED
@@ -1,25 +1,23 @@
1
+ import React, { useMemo } from 'react';
1
2
  import { Routes, Route } from 'react-router-dom';
3
+ import classnames from 'classnames';
4
+ import { compact, flatten, groupBy, isFunction } from 'lodash';
5
+ import * as semver from 'semver';
6
+ import { DropdownComponentVersion, GetActiveTabIndex, VersionDropdown } from '@teambit/component.ui.version-dropdown';
2
7
  import { MainDropdown, MenuItemSlot } from '@teambit/ui-foundation.ui.main-dropdown';
3
- import { VersionDropdown } from '@teambit/component.ui.version-dropdown';
4
- import { FullLoader } from '@teambit/ui-foundation.ui.full-loader';
5
8
  import type { ConsumeMethod } from '@teambit/ui-foundation.ui.use-box.menu';
6
9
  import { useLocation } from '@teambit/base-react.navigation.link';
7
- import { flatten, groupBy, compact, isFunction } from 'lodash';
8
- import classnames from 'classnames';
9
- import React, { useMemo } from 'react';
10
10
  import { UseBoxDropdown } from '@teambit/ui-foundation.ui.use-box.dropdown';
11
- import { useLanes } from '@teambit/lanes.hooks.use-lanes';
12
- import { LaneModel } from '@teambit/lanes.ui.models.lanes-model';
11
+ import { useLanes as defaultUseLanes } from '@teambit/lanes.hooks.use-lanes';
12
+ import { LanesModel } from '@teambit/lanes.ui.models.lanes-model';
13
13
  import { Menu as ConsumeMethodsMenu } from '@teambit/ui-foundation.ui.use-box.menu';
14
14
  import { LegacyComponentLog } from '@teambit/legacy-component-log';
15
- import type { ComponentModel } from '../component-model';
16
- import { useComponent as useComponentQuery, UseComponentType } from '../use-component';
15
+ import { useComponent as useComponentQuery, UseComponentType, Filters } from '../use-component';
17
16
  import { CollapsibleMenuNav } from './menu-nav';
18
- import styles from './menu.module.scss';
19
- import { OrderedNavigationSlot, ConsumeMethodSlot } from './nav-plugin';
17
+ import { OrderedNavigationSlot, ConsumeMethodSlot, ConsumePluginProps } from './nav-plugin';
20
18
  import { useIdFromLocation } from '../use-component-from-location';
21
19
  import { ComponentID } from '../..';
22
- import { Filters } from '../use-component-query';
20
+ import styles from './menu.module.scss';
23
21
 
24
22
  export type MenuProps = {
25
23
  className?: string;
@@ -54,9 +52,14 @@ export type MenuProps = {
54
52
 
55
53
  useComponent?: UseComponentType;
56
54
 
57
- path?: string;
58
-
59
55
  useComponentFilters?: () => Filters;
56
+
57
+ useLanes?: () => {
58
+ loading?: boolean;
59
+ lanesModel?: LanesModel;
60
+ };
61
+
62
+ path?: string;
60
63
  };
61
64
  function getComponentIdStr(componentIdStr?: string | (() => string | undefined)): string | undefined {
62
65
  if (isFunction(componentIdStr)) return componentIdStr();
@@ -83,22 +86,27 @@ export function ComponentMenu({
83
86
  const _componentIdStr = getComponentIdStr(componentIdStr);
84
87
  const componentId = _componentIdStr ? ComponentID.fromString(_componentIdStr) : undefined;
85
88
  const resolvedComponentIdStr = path || idFromLocation;
86
-
87
- const useComponentOptions = {
88
- logFilters: useComponentFilters?.(),
89
- customUseComponent: useComponent,
90
- };
91
-
92
- const { component } = useComponentQuery(host, componentId?.toString() || idFromLocation, useComponentOptions);
93
89
  const mainMenuItems = useMemo(() => groupBy(flatten(menuItemSlot.values()), 'category'), [menuItemSlot]);
94
-
95
- if (!component) return <FullLoader />;
90
+ const componentFilters = useComponentFilters?.() || {};
91
+ const useComponentVersions = defaultLoadVersions(
92
+ host,
93
+ componentId?.toString() || idFromLocation,
94
+ componentFilters,
95
+ useComponent
96
+ );
96
97
 
97
98
  const RightSide = (
98
99
  <div className={styles.rightSide}>
99
100
  {RightNode || (
100
101
  <>
101
- <VersionRelatedDropdowns component={component} consumeMethods={consumeMethodSlot} host={host} />
102
+ <VersionRelatedDropdowns
103
+ host={host}
104
+ consumeMethods={consumeMethodSlot}
105
+ componentId={componentId?.toString() || idFromLocation}
106
+ useComponent={useComponentVersions}
107
+ componentFilters={componentFilters}
108
+ // loading={loading}
109
+ />
102
110
  <MainDropdown className={styles.hideOnMobile} menuItems={mainMenuItems} />
103
111
  </>
104
112
  )}
@@ -122,91 +130,211 @@ export function ComponentMenu({
122
130
  );
123
131
  }
124
132
 
125
- export function VersionRelatedDropdowns({
126
- component,
127
- consumeMethods,
128
- className,
129
- host,
130
- }: {
131
- component: ComponentModel;
133
+ export type VersionRelatedDropdownsProps = {
134
+ componentId?: string;
132
135
  consumeMethods?: ConsumeMethodSlot;
136
+ componentFilters?: Filters;
137
+ useComponent?: UseComponentVersions;
133
138
  className?: string;
139
+ loading?: boolean;
134
140
  host: string;
135
- }) {
141
+ useLanes?: () => {
142
+ loading?: boolean;
143
+ lanesModel?: LanesModel;
144
+ };
145
+ dropdownOptions?: {
146
+ showVersionDetails?: boolean;
147
+ getActiveTabIndex?: GetActiveTabIndex;
148
+ };
149
+ };
150
+ export type UseComponentVersionsProps = {
151
+ skip?: boolean;
152
+ id?: string;
153
+ initialLoad?: boolean;
154
+ };
155
+ export type UseComponentVersionProps = {
156
+ skip?: boolean;
157
+ version?: string;
158
+ };
159
+ export type UseComponentVersions = (props?: UseComponentVersionsProps) => UseComponentVersionsResult;
160
+ export type UseComponentVersion = (props?: UseComponentVersionProps) => DropdownComponentVersion | undefined;
161
+ export type UseComponentVersionsResult = {
162
+ tags?: DropdownComponentVersion[];
163
+ snaps?: DropdownComponentVersion[];
164
+ id?: ComponentID;
165
+ packageName?: string;
166
+ latest?: string;
167
+ currentVersion?: string;
168
+ loading?: boolean;
169
+ };
170
+
171
+ export function defaultLoadVersions(
172
+ host: string,
173
+ componentId?: string,
174
+ componentFilters: Filters = {},
175
+ useComponent?: UseComponentType,
176
+ loadingFromProps?: boolean
177
+ ): UseComponentVersions {
178
+ return React.useCallback(
179
+ (_props) => {
180
+ const { skip, initialLoad } = _props || {};
181
+ const fetchOptions = {
182
+ logFilters: {
183
+ ...componentFilters,
184
+ log: {
185
+ ...componentFilters.log,
186
+ limit: initialLoad ? 3 : undefined,
187
+ },
188
+ },
189
+ skip: loadingFromProps || skip,
190
+ customUseComponent: useComponent,
191
+ };
192
+ const {
193
+ component,
194
+ loading: loadingComponent,
195
+ componentLogs = {},
196
+ } = useComponentQuery(host, componentId, fetchOptions);
197
+ const logs = componentLogs?.logs;
198
+ const loading = React.useMemo(
199
+ () => loadingComponent || loadingFromProps || componentLogs.loading,
200
+ [loadingComponent, loadingFromProps, componentLogs.loading]
201
+ );
202
+
203
+ const snaps = useMemo(() => {
204
+ return (logs || []).filter((log) => !log.tag).map((snap) => ({ ...snap, version: snap.hash }));
205
+ }, [logs]);
206
+
207
+ const tags = useMemo(() => {
208
+ const tagLookup = new Map<string, LegacyComponentLog>();
209
+ (logs || [])
210
+ .filter((log) => log.tag)
211
+ .forEach((tag) => {
212
+ tagLookup.set(tag?.tag as string, tag);
213
+ });
214
+ return compact(
215
+ (component?.tags?.toArray() || []).reverse().map((tag) => tagLookup.get(tag.version.version))
216
+ ).map((tag) => ({ ...tag, version: tag.tag as string }));
217
+ }, [logs]);
218
+
219
+ return {
220
+ loading,
221
+ id: component?.id,
222
+ packageName: component?.packageName,
223
+ latestVersion: component?.latest,
224
+ currentVersion: component?.version,
225
+ snaps,
226
+ tags,
227
+ buildStatus: component?.buildStatus,
228
+ };
229
+ },
230
+ [componentId, loadingFromProps, componentFilters]
231
+ );
232
+ }
233
+
234
+ export const defaultLoadCurrentVersion: (props: VersionRelatedDropdownsProps) => UseComponentVersion = (props) => {
235
+ return (_props) => {
236
+ const { skip, version: _version } = _props || {};
237
+ const { snaps, tags, currentVersion, loading } = props.useComponent?.({ skip, id: props.componentId }) ?? {};
238
+ const version = _version ?? currentVersion;
239
+ const isTag = React.useMemo(() => semver.valid(version), [loading, version]);
240
+ if (isTag) {
241
+ return React.useMemo(() => tags?.find((tag) => tag.tag === version), [loading, tags?.length, version]);
242
+ }
243
+ return React.useMemo(() => snaps?.find((snap) => snap.version === version), [loading, snaps?.length, version]);
244
+ };
245
+ };
246
+
247
+ export function VersionRelatedDropdowns(props: VersionRelatedDropdownsProps) {
248
+ const updatedPropsWithDefaults = {
249
+ ...props,
250
+ useLanes: props.useLanes ?? defaultUseLanes,
251
+ dropdownOptions: {
252
+ ...props.dropdownOptions,
253
+ showVersionDetails: props?.dropdownOptions?.showVersionDetails ?? true,
254
+ },
255
+ };
256
+
257
+ const loadVersion = defaultLoadCurrentVersion(updatedPropsWithDefaults);
258
+
259
+ const { useLanes, consumeMethods, className, dropdownOptions, host } = updatedPropsWithDefaults;
260
+ const {
261
+ loading,
262
+ id,
263
+ tags,
264
+ snaps,
265
+ latest,
266
+ packageName,
267
+ currentVersion: _currentVersion,
268
+ } = props.useComponent?.({ initialLoad: true }) || {};
136
269
  const location = useLocation();
137
270
  const { lanesModel } = useLanes();
271
+ const lanes = id ? lanesModel?.getLanesByComponentId(id)?.filter((lane) => !lane.id.isDefault()) || [] : [];
138
272
  const viewedLane =
139
273
  lanesModel?.viewedLane?.id && !lanesModel?.viewedLane?.id.isDefault() ? lanesModel.viewedLane : undefined;
140
274
 
141
- const { logs } = component;
142
275
  const isWorkspace = host === 'teambit.workspace/workspace';
143
276
 
144
- const snaps = useMemo(() => {
145
- return (logs || []).filter((log) => !log.tag).map((snap) => ({ ...snap, version: snap.hash }));
146
- }, [logs]);
147
-
148
- const tags = useMemo(() => {
149
- const tagLookup = new Map<string, LegacyComponentLog>();
150
- (logs || [])
151
- .filter((log) => log.tag)
152
- .forEach((tag) => {
153
- tagLookup.set(tag?.tag as string, tag);
154
- });
155
- return compact(
156
- component.tags
157
- ?.toArray()
158
- .reverse()
159
- .map((tag) => tagLookup.get(tag.version.version))
160
- ).map((tag) => ({ ...tag, version: tag.tag as string }));
161
- }, [logs]);
162
-
163
- const isNew = snaps.length === 0 && tags.length === 0;
164
-
165
- const lanes = lanesModel?.getLanesByComponentId(component.id)?.filter((lane) => !lane.id.isDefault()) || [];
277
+ const isNew = tags?.length === 0 && snaps?.length === 0;
278
+
166
279
  const localVersion = isWorkspace && !isNew && (!viewedLane || lanesModel?.isViewingCurrentLane());
167
280
 
168
281
  const currentVersion =
169
- isWorkspace && !isNew && !location?.search.includes('version') ? 'workspace' : component.version;
282
+ isWorkspace && !isNew && !location?.search.includes('version') ? 'workspace' : _currentVersion ?? '';
283
+
284
+ const consumeMethodProps: ConsumePluginProps | undefined = React.useMemo(() => {
285
+ return id
286
+ ? {
287
+ id,
288
+ packageName: packageName ?? '',
289
+ latest,
290
+ options: { viewedLane, disableInstall: !packageName },
291
+ }
292
+ : undefined;
293
+ }, [id, packageName, latest, viewedLane]);
294
+
295
+ const methods = useConsumeMethods(consumeMethods, consumeMethodProps);
296
+ const hasMethods = methods?.length > 0;
170
297
 
171
- const methods = useConsumeMethods(component, consumeMethods, viewedLane);
172
298
  return (
173
299
  <>
174
- {consumeMethods && tags.length > 0 && (
300
+ {consumeMethods && id && hasMethods && (
175
301
  <UseBoxDropdown
176
302
  position="bottom-end"
177
303
  className={classnames(styles.useBox, styles.hideOnMobile)}
178
- Menu={<ConsumeMethodsMenu methods={methods} componentName={component.id.name} />}
304
+ Menu={<ConsumeMethodsMenu methods={methods} componentName={id.name} />}
179
305
  />
180
306
  )}
181
307
  <VersionDropdown
182
- tags={tags}
183
- snaps={snaps}
184
308
  lanes={lanes}
309
+ loading={loading}
310
+ useComponentVersions={props.useComponent}
311
+ hasMoreVersions={!isNew}
312
+ useCurrentVersionLog={loadVersion}
185
313
  localVersion={localVersion}
186
314
  currentVersion={currentVersion}
187
- latestVersion={component.latest}
315
+ latestVersion={latest}
188
316
  currentLane={viewedLane}
189
317
  className={className}
190
318
  menuClassName={styles.componentVersionMenu}
319
+ getActiveTabIndex={dropdownOptions?.getActiveTabIndex}
320
+ showVersionDetails={dropdownOptions?.showVersionDetails}
191
321
  />
192
322
  </>
193
323
  );
194
324
  }
195
325
 
196
326
  function useConsumeMethods(
197
- componentModel?: ComponentModel,
198
327
  consumeMethods?: ConsumeMethodSlot,
199
- currentLane?: LaneModel
328
+ consumePluginProps?: ConsumePluginProps
200
329
  ): ConsumeMethod[] {
201
- // if (!consumeMethods || !componentModel) return [];
202
330
  return useMemo(
203
331
  () =>
204
332
  flatten(consumeMethods?.values())
205
333
  .map((method) => {
206
- if (!componentModel) return undefined;
207
- return method?.(componentModel, { currentLane });
334
+ if (!consumePluginProps) return undefined;
335
+ return method?.(consumePluginProps);
208
336
  })
209
337
  .filter((x) => !!x && x.Component && x.Title) as ConsumeMethod[],
210
- [consumeMethods, componentModel, currentLane]
338
+ [consumeMethods, consumePluginProps]
211
339
  );
212
340
  }
@@ -2,7 +2,7 @@ import { SlotRegistry } from '@teambit/harmony';
2
2
  import type { LinkProps } from '@teambit/base-react.navigation.link';
3
3
  import type { ConsumeMethod } from '@teambit/ui-foundation.ui.use-box.menu';
4
4
  import { LaneModel } from '@teambit/lanes.ui.models.lanes-model';
5
- import { ComponentModel } from '../../ui';
5
+ import { ComponentID, ComponentModel } from '../..';
6
6
 
7
7
  export type NavPluginProps = {
8
8
  displayName?: string;
@@ -16,12 +16,20 @@ export type NavPlugin = {
16
16
 
17
17
  export type OrderedNavigationSlot = SlotRegistry<NavPlugin>;
18
18
  export type ConsumePluginOptions = {
19
- currentLane?: LaneModel;
19
+ viewedLane?: LaneModel;
20
+ hide?: boolean;
21
+ disableInstall?: boolean;
20
22
  };
21
23
 
22
- export type ConsumePlugin = (
23
- componentModel: ComponentModel,
24
- options?: ConsumePluginOptions
25
- ) => ConsumeMethod | undefined;
24
+ export type ConsumePluginProps = {
25
+ id: ComponentID;
26
+ packageName: string;
27
+ latest?: string;
28
+ // @deprecated - pass id, packageName and latest instead via props
29
+ componentModel?: ComponentModel;
30
+ options?: ConsumePluginOptions;
31
+ };
32
+
33
+ export type ConsumePlugin = (props: ConsumePluginProps) => ConsumeMethod | undefined;
26
34
 
27
35
  export type ConsumeMethodSlot = SlotRegistry<ConsumePlugin[]>;
@@ -0,0 +1,65 @@
1
+ import { LegacyComponentLog } from '@teambit/legacy-component-log';
2
+ import { useDataQuery } from '@teambit/ui-foundation.ui.hooks.use-data-query';
3
+ import { ComponentLogsResult, Filters } from './use-component.model';
4
+ import { GET_COMPONENT_WITH_LOGS } from './use-component.fragments';
5
+ import { ComponentError } from './component-error';
6
+ import { getOffsetValue } from './use-component.utils';
7
+
8
+ export function useComponentLogs(
9
+ componentId: string,
10
+ host: string,
11
+ filters?: Filters,
12
+ skipFromProps?: boolean
13
+ ): ComponentLogsResult {
14
+ const { variables, skip } = useComponentLogsInit(componentId, host, filters, skipFromProps);
15
+
16
+ const { data, error, loading } = useDataQuery(GET_COMPONENT_WITH_LOGS, {
17
+ variables,
18
+ skip,
19
+ errorPolicy: 'all',
20
+ });
21
+
22
+ const rawComponent = data?.getHost?.get;
23
+ const rawCompLogs: Array<LegacyComponentLog> = rawComponent?.logs;
24
+
25
+ const componentError =
26
+ error && !data
27
+ ? new ComponentError(500, error.message)
28
+ : (!rawComponent && !loading && new ComponentError(404)) || undefined;
29
+
30
+ return {
31
+ loading,
32
+ error: componentError,
33
+ componentLogs: {
34
+ logs: rawCompLogs,
35
+ loading,
36
+ },
37
+ };
38
+ }
39
+
40
+ export function useComponentLogsInit(componentId: string, host: string, filters?: Filters, skip?: boolean) {
41
+ const { log } = filters || {};
42
+ const {
43
+ head: logHead,
44
+ offset: logOffset,
45
+ sort: logSort,
46
+ limit: logLimit,
47
+ type: logType,
48
+ takeHeadFromComponent: logTakeHeadFromComponent,
49
+ } = log || {};
50
+ const variables = {
51
+ id: componentId,
52
+ extensionId: host,
53
+ logOffset: getOffsetValue(logOffset, logLimit),
54
+ logLimit,
55
+ logType,
56
+ logHead,
57
+ logSort,
58
+ logTakeHeadFromComponent,
59
+ };
60
+ return {
61
+ logOffset,
62
+ variables,
63
+ skip,
64
+ };
65
+ }
@@ -1,168 +1,42 @@
1
1
  import { useMemo, useEffect, useRef } from 'react';
2
- import { gql } from '@apollo/client';
3
2
  import { useDataQuery } from '@teambit/ui-foundation.ui.hooks.use-data-query';
4
3
  import { ComponentID, ComponentIdObj } from '@teambit/component-id';
5
4
  import { ComponentDescriptor } from '@teambit/component-descriptor';
6
-
7
5
  import { ComponentModel } from './component-model';
6
+ import { ComponentQueryResult, Filters } from './use-component.model';
7
+ import {
8
+ GET_COMPONENT,
9
+ SUB_COMPONENT_CHANGED,
10
+ SUB_COMPONENT_REMOVED,
11
+ SUB_SUBSCRIPTION_ADDED,
12
+ } from './use-component.fragments';
13
+ import { useComponentLogs } from './use-component-logs';
8
14
  import { ComponentError } from './component-error';
9
15
 
10
- export const componentIdFields = gql`
11
- fragment componentIdFields on ComponentID {
12
- name
13
- version
14
- scope
15
- }
16
- `;
17
-
18
- export const componentOverviewFields = gql`
19
- fragment componentOverviewFields on Component {
20
- id {
21
- ...componentIdFields
22
- }
23
- aspects(include: ["teambit.preview/preview", "teambit.envs/envs"]) {
24
- # 'id' property in gql refers to a *global* identifier and used for caching.
25
- # this makes aspect data cache under the same key, even when they are under different components.
26
- # renaming the property fixes that.
27
- id
28
- data
29
- }
30
- elementsUrl
31
- description
32
- deprecation {
33
- isDeprecate
34
- newId
35
- }
36
- labels
37
- displayName
38
- server {
39
- env
40
- url
41
- host
42
- basePath
43
- }
44
- buildStatus
45
- env {
46
- id
47
- icon
48
- }
49
- size {
50
- compressedTotal
51
- }
52
- preview {
53
- includesEnvTemplate
54
- legacyHeader
55
- isScaling
56
- skipIncludes
57
- }
58
- compositions {
59
- identifier
60
- displayName
61
- }
62
- }
63
- ${componentIdFields}
64
- `;
65
-
66
- export const componentFields = gql`
67
- fragment componentFields on Component {
68
- id {
69
- ...componentIdFields
70
- }
71
- ...componentOverviewFields
72
- packageName
73
- latest
74
- compositions {
75
- identifier
76
- displayName
77
- }
78
- tags {
79
- version
80
- }
81
- logs(type: $logType, offset: $logOffset, limit: $logLimit, head: $logHead, sort: $logSort) {
82
- id
83
- message
84
- username
85
- email
86
- date
87
- hash
88
- tag
89
- }
90
- }
91
- ${componentIdFields}
92
- ${componentOverviewFields}
93
- `;
94
-
95
- const GET_COMPONENT = gql`
96
- query Component(
97
- $id: String!
98
- $extensionId: String!
99
- $logType: String
100
- $logOffset: Int
101
- $logLimit: Int
102
- $logHead: String
103
- $logSort: String
104
- ) {
105
- getHost(id: $extensionId) {
106
- id # used for GQL caching
107
- get(id: $id) {
108
- ...componentFields
109
- }
110
- }
111
- }
112
- ${componentFields}
113
- `;
114
-
115
- const SUB_SUBSCRIPTION_ADDED = gql`
116
- subscription OnComponentAdded($logType: String, $logOffset: Int, $logLimit: Int, $logHead: String, $logSort: String) {
117
- componentAdded {
118
- component {
119
- ...componentFields
120
- }
121
- }
122
- }
123
- ${componentFields}
124
- `;
125
-
126
- const SUB_COMPONENT_CHANGED = gql`
127
- subscription OnComponentChanged(
128
- $logType: String
129
- $logOffset: Int
130
- $logLimit: Int
131
- $logHead: String
132
- $logSort: String
133
- ) {
134
- componentChanged {
135
- component {
136
- ...componentFields
137
- }
138
- }
139
- }
140
- ${componentFields}
141
- `;
142
-
143
- const SUB_COMPONENT_REMOVED = gql`
144
- subscription OnComponentRemoved {
145
- componentRemoved {
146
- componentIds {
147
- ...componentIdFields
148
- }
149
- }
150
- }
151
- ${componentIdFields}
152
- `;
153
- export type Filters = {
154
- log?: { logType?: string; logOffset?: number; logLimit?: number; logHead?: string; logSort?: string };
155
- };
156
16
  /** provides data to component ui page, making sure both variables and return value are safely typed and memoized */
157
- export function useComponentQuery(componentId: string, host: string, filters?: Filters, skip?: boolean) {
17
+ export function useComponentQuery(
18
+ componentId: string,
19
+ host: string,
20
+ filters?: Filters,
21
+ skip?: boolean
22
+ ): ComponentQueryResult {
158
23
  const idRef = useRef(componentId);
159
24
  idRef.current = componentId;
160
- const { data, error, loading, subscribeToMore, ...rest } = useDataQuery(GET_COMPONENT, {
161
- variables: { id: componentId, extensionId: host, ...(filters?.log || {}) },
25
+ const variables = {
26
+ id: componentId,
27
+ extensionId: host,
28
+ };
29
+
30
+ const { data, error, loading, subscribeToMore } = useDataQuery(GET_COMPONENT, {
31
+ variables,
162
32
  skip,
163
33
  errorPolicy: 'all',
164
34
  });
165
35
 
36
+ const { loading: loadingLogs, componentLogs: { logs } = {} } = useComponentLogs(componentId, host, filters, skip);
37
+
38
+ const rawComponent = data?.getHost?.get;
39
+
166
40
  useEffect(() => {
167
41
  // @TODO @Kutner fix subscription for scope
168
42
  if (host !== 'teambit.workspace/workspace') {
@@ -247,8 +121,26 @@ export function useComponentQuery(componentId: string, host: string, filters?: F
247
121
  };
248
122
  }, []);
249
123
 
250
- const rawComponent = data?.getHost?.get;
251
- return useMemo(() => {
124
+ const idDepKey = rawComponent?.id
125
+ ? `${rawComponent?.id?.scope}/${rawComponent?.id?.name}@${rawComponent?.id?.version}}`
126
+ : undefined;
127
+
128
+ const id: ComponentID | undefined = useMemo(
129
+ () => (rawComponent ? ComponentID.fromObject(rawComponent.id) : undefined),
130
+ [idDepKey]
131
+ );
132
+
133
+ const componentError =
134
+ error && !data
135
+ ? new ComponentError(500, error.message)
136
+ : (!rawComponent && !loading && new ComponentError(404)) || undefined;
137
+
138
+ const component = useMemo(
139
+ () => (rawComponent ? ComponentModel.from({ ...rawComponent, host, logs }) : undefined),
140
+ [id?.toString(), logs]
141
+ );
142
+
143
+ const componentDescriptor = useMemo(() => {
252
144
  const aspectList = {
253
145
  entries: rawComponent?.aspects.map((aspectObject) => {
254
146
  return {
@@ -258,15 +150,20 @@ export function useComponentQuery(componentId: string, host: string, filters?: F
258
150
  };
259
151
  }),
260
152
  };
261
- const id = rawComponent && ComponentID.fromObject(rawComponent.id);
262
- const componentError =
263
- error && !data ? new ComponentError(500, error.message) : !rawComponent && !loading && new ComponentError(404);
153
+
154
+ return id ? ComponentDescriptor.fromObject({ id: id.toString(), aspectList }) : undefined;
155
+ }, [id?.toString()]);
156
+
157
+ return useMemo(() => {
264
158
  return {
265
- componentDescriptor: id ? ComponentDescriptor.fromObject({ id: id.toString(), aspectList }) : undefined,
266
- component: rawComponent ? ComponentModel.from({ ...rawComponent, host }) : undefined,
159
+ componentDescriptor,
160
+ component,
161
+ componentLogs: {
162
+ loading: loadingLogs,
163
+ logs,
164
+ },
267
165
  error: componentError || undefined,
268
166
  loading,
269
- ...rest,
270
167
  };
271
- }, [rawComponent, host, error]);
168
+ }, [host, component, componentDescriptor, componentError]);
272
169
  }