Fix/record group index and seed (#9605)
- [x] [Disable group by on default view Options menu](https://discord.com/channels/1130383047699738754/1328421803399446568) - [x] Add default seed for view group
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
import {
|
import {
|
||||||
|
AppTooltip,
|
||||||
IconFileExport,
|
IconFileExport,
|
||||||
IconFileImport,
|
IconFileImport,
|
||||||
IconLayout,
|
IconLayout,
|
||||||
@ -55,6 +56,10 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
|||||||
recordGroupFieldMetadataComponentState,
|
recordGroupFieldMetadataComponentState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isGroupByEnabled =
|
||||||
|
(isDefined(currentView?.viewGroups) && currentView.viewGroups.length > 0) ||
|
||||||
|
currentView?.key !== 'INDEX';
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
[Key.Escape],
|
[Key.Escape],
|
||||||
() => {
|
() => {
|
||||||
@ -115,20 +120,34 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
|||||||
contextualText={`${visibleBoardFields.length} shown`}
|
contextualText={`${visibleBoardFields.length} shown`}
|
||||||
hasSubMenu
|
hasSubMenu
|
||||||
/>
|
/>
|
||||||
{viewType === ViewType.Kanban ||
|
|
||||||
(currentView?.key !== 'INDEX' && (
|
<div id="group-by-menu-item">
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
isDefined(recordGroupFieldMetadata)
|
isDefined(recordGroupFieldMetadata)
|
||||||
? onContentChange('recordGroups')
|
? onContentChange('recordGroups')
|
||||||
: onContentChange('recordGroupFields')
|
: onContentChange('recordGroupFields')
|
||||||
}
|
}
|
||||||
LeftIcon={IconLayoutList}
|
LeftIcon={IconLayoutList}
|
||||||
text="Group by"
|
text="Group by"
|
||||||
contextualText={recordGroupFieldMetadata?.label}
|
contextualText={
|
||||||
hasSubMenu
|
!isGroupByEnabled
|
||||||
/>
|
? 'Not available on Default View'
|
||||||
))}
|
: recordGroupFieldMetadata?.label
|
||||||
|
}
|
||||||
|
hasSubMenu
|
||||||
|
disabled={!isGroupByEnabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{!isGroupByEnabled && (
|
||||||
|
<AppTooltip
|
||||||
|
anchorSelect={`#group-by-menu-item`}
|
||||||
|
content="Not available on Default View"
|
||||||
|
noArrow
|
||||||
|
place="bottom"
|
||||||
|
width="100%"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
|
|||||||
@ -45,7 +45,9 @@ import { SURVEY_RESULTS_METADATA_SEEDS } from 'src/engine/seeder/metadata-seeds/
|
|||||||
import { SeederService } from 'src/engine/seeder/seeder.service';
|
import { SeederService } from 'src/engine/seeder/seeder.service';
|
||||||
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
|
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
|
import { createWorkspaceViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/create-workspace-views';
|
||||||
import { seedViewWithDemoData } from 'src/engine/workspace-manager/standard-objects-prefill-data/seed-view-with-demo-data';
|
import { seedViewWithDemoData } from 'src/engine/workspace-manager/standard-objects-prefill-data/seed-view-with-demo-data';
|
||||||
|
import { opportunitiesTableByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-table-by-stage.view';
|
||||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||||
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||||
|
|
||||||
@ -230,6 +232,14 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
|
|||||||
isWorkflowEnabled,
|
isWorkflowEnabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const devViewDefinitionsWithId = await createWorkspaceViews(
|
||||||
|
entityManager,
|
||||||
|
dataSourceMetadata.schema,
|
||||||
|
[opportunitiesTableByStageView(objectMetadataStandardIdToIdMap)],
|
||||||
|
);
|
||||||
|
|
||||||
|
viewDefinitionsWithId.push(...devViewDefinitionsWithId);
|
||||||
|
|
||||||
await seedWorkspaceFavorites(
|
await seedWorkspaceFavorites(
|
||||||
viewDefinitionsWithId
|
viewDefinitionsWithId
|
||||||
.filter(
|
.filter(
|
||||||
|
|||||||
@ -0,0 +1,131 @@
|
|||||||
|
import { EntityManager } from 'typeorm';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
import { ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||||
|
|
||||||
|
export const createWorkspaceViews = async (
|
||||||
|
entityManager: EntityManager,
|
||||||
|
schemaName: string,
|
||||||
|
viewDefinitions: ViewDefinition[],
|
||||||
|
) => {
|
||||||
|
const viewDefinitionsWithId = viewDefinitions.map((viewDefinition) => ({
|
||||||
|
...viewDefinition,
|
||||||
|
id: v4(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.view`, [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'objectMetadataId',
|
||||||
|
'type',
|
||||||
|
'key',
|
||||||
|
'position',
|
||||||
|
'icon',
|
||||||
|
'kanbanFieldMetadataId',
|
||||||
|
])
|
||||||
|
.values(
|
||||||
|
viewDefinitionsWithId.map(
|
||||||
|
({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
objectMetadataId,
|
||||||
|
type,
|
||||||
|
key,
|
||||||
|
position,
|
||||||
|
icon,
|
||||||
|
kanbanFieldMetadataId,
|
||||||
|
}) => ({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
objectMetadataId,
|
||||||
|
type,
|
||||||
|
key,
|
||||||
|
position,
|
||||||
|
icon,
|
||||||
|
kanbanFieldMetadataId,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.returning('*')
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
for (const viewDefinition of viewDefinitionsWithId) {
|
||||||
|
if (viewDefinition.fields && viewDefinition.fields.length > 0) {
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.viewField`, [
|
||||||
|
'fieldMetadataId',
|
||||||
|
'position',
|
||||||
|
'isVisible',
|
||||||
|
'size',
|
||||||
|
'viewId',
|
||||||
|
])
|
||||||
|
.values(
|
||||||
|
viewDefinition.fields.map((field) => ({
|
||||||
|
fieldMetadataId: field.fieldMetadataId,
|
||||||
|
position: field.position,
|
||||||
|
isVisible: field.isVisible,
|
||||||
|
size: field.size,
|
||||||
|
viewId: viewDefinition.id,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (viewDefinition.filters && viewDefinition.filters.length > 0) {
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.viewFilter`, [
|
||||||
|
'fieldMetadataId',
|
||||||
|
'displayValue',
|
||||||
|
'operand',
|
||||||
|
'value',
|
||||||
|
'viewId',
|
||||||
|
])
|
||||||
|
.values(
|
||||||
|
viewDefinition.filters.map((filter: any) => ({
|
||||||
|
fieldMetadataId: filter.fieldMetadataId,
|
||||||
|
displayValue: filter.displayValue,
|
||||||
|
operand: filter.operand,
|
||||||
|
value: filter.value,
|
||||||
|
viewId: viewDefinition.id,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
'groups' in viewDefinition &&
|
||||||
|
viewDefinition.groups &&
|
||||||
|
viewDefinition.groups.length > 0
|
||||||
|
) {
|
||||||
|
await entityManager
|
||||||
|
.createQueryBuilder()
|
||||||
|
.insert()
|
||||||
|
.into(`${schemaName}.viewGroup`, [
|
||||||
|
'fieldMetadataId',
|
||||||
|
'isVisible',
|
||||||
|
'fieldValue',
|
||||||
|
'position',
|
||||||
|
'viewId',
|
||||||
|
])
|
||||||
|
.values(
|
||||||
|
viewDefinition.groups.map((group: any) => ({
|
||||||
|
fieldMetadataId: group.fieldMetadataId,
|
||||||
|
isVisible: group.isVisible,
|
||||||
|
fieldValue: group.fieldValue,
|
||||||
|
position: group.position,
|
||||||
|
viewId: viewDefinition.id,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewDefinitionsWithId;
|
||||||
|
};
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import { EntityManager } from 'typeorm';
|
import { EntityManager } from 'typeorm';
|
||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||||
|
|
||||||
|
import { createWorkspaceViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/create-workspace-views';
|
||||||
import { seedCompaniesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view';
|
import { seedCompaniesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view';
|
||||||
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
|
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
|
||||||
import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view';
|
import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view';
|
||||||
@ -37,124 +37,5 @@ export const seedViewWithDemoData = async (
|
|||||||
: []),
|
: []),
|
||||||
];
|
];
|
||||||
|
|
||||||
const viewDefinitionsWithId = viewDefinitions.map((viewDefinition) => ({
|
return createWorkspaceViews(entityManager, schemaName, viewDefinitions);
|
||||||
...viewDefinition,
|
|
||||||
id: v4(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
await entityManager
|
|
||||||
.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${schemaName}.view`, [
|
|
||||||
'id',
|
|
||||||
'name',
|
|
||||||
'objectMetadataId',
|
|
||||||
'type',
|
|
||||||
'key',
|
|
||||||
'position',
|
|
||||||
'icon',
|
|
||||||
'kanbanFieldMetadataId',
|
|
||||||
])
|
|
||||||
.values(
|
|
||||||
viewDefinitionsWithId.map(
|
|
||||||
({
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
objectMetadataId,
|
|
||||||
type,
|
|
||||||
key,
|
|
||||||
position,
|
|
||||||
icon,
|
|
||||||
kanbanFieldMetadataId,
|
|
||||||
}) => ({
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
objectMetadataId,
|
|
||||||
type,
|
|
||||||
key,
|
|
||||||
position,
|
|
||||||
icon,
|
|
||||||
kanbanFieldMetadataId,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.returning('*')
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
for (const viewDefinition of viewDefinitionsWithId) {
|
|
||||||
if (viewDefinition.fields && viewDefinition.fields.length > 0) {
|
|
||||||
await entityManager
|
|
||||||
.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${schemaName}.viewField`, [
|
|
||||||
'fieldMetadataId',
|
|
||||||
'position',
|
|
||||||
'isVisible',
|
|
||||||
'size',
|
|
||||||
'viewId',
|
|
||||||
])
|
|
||||||
.values(
|
|
||||||
viewDefinition.fields.map((field) => ({
|
|
||||||
fieldMetadataId: field.fieldMetadataId,
|
|
||||||
position: field.position,
|
|
||||||
isVisible: field.isVisible,
|
|
||||||
size: field.size,
|
|
||||||
viewId: viewDefinition.id,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (viewDefinition.filters && viewDefinition.filters.length > 0) {
|
|
||||||
await entityManager
|
|
||||||
.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${schemaName}.viewFilter`, [
|
|
||||||
'fieldMetadataId',
|
|
||||||
'displayValue',
|
|
||||||
'operand',
|
|
||||||
'value',
|
|
||||||
'viewId',
|
|
||||||
])
|
|
||||||
.values(
|
|
||||||
viewDefinition.filters.map((filter: any) => ({
|
|
||||||
fieldMetadataId: filter.fieldMetadataId,
|
|
||||||
displayValue: filter.displayValue,
|
|
||||||
operand: filter.operand,
|
|
||||||
value: filter.value,
|
|
||||||
viewId: viewDefinition.id,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
'groups' in viewDefinition &&
|
|
||||||
viewDefinition.groups &&
|
|
||||||
viewDefinition.groups.length > 0
|
|
||||||
) {
|
|
||||||
await entityManager
|
|
||||||
.createQueryBuilder()
|
|
||||||
.insert()
|
|
||||||
.into(`${schemaName}.viewGroup`, [
|
|
||||||
'fieldMetadataId',
|
|
||||||
'isVisible',
|
|
||||||
'fieldValue',
|
|
||||||
'position',
|
|
||||||
'viewId',
|
|
||||||
])
|
|
||||||
.values(
|
|
||||||
viewDefinition.groups.map((group: any) => ({
|
|
||||||
fieldMetadataId: group.fieldMetadataId,
|
|
||||||
isVisible: group.isVisible,
|
|
||||||
fieldValue: group.fieldValue,
|
|
||||||
position: group.position,
|
|
||||||
viewId: viewDefinition.id,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return viewDefinitionsWithId;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
export interface ViewDefinition {
|
||||||
|
id?: string;
|
||||||
|
name: string;
|
||||||
|
objectMetadataId: string;
|
||||||
|
type: string;
|
||||||
|
key: string | null;
|
||||||
|
position: number;
|
||||||
|
icon?: string;
|
||||||
|
kanbanFieldMetadataId?: string;
|
||||||
|
fields?: {
|
||||||
|
fieldMetadataId: string;
|
||||||
|
position: number;
|
||||||
|
isVisible: boolean;
|
||||||
|
size: number;
|
||||||
|
}[];
|
||||||
|
filters?: {
|
||||||
|
fieldMetadataId: string;
|
||||||
|
displayValue: string;
|
||||||
|
operand: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
groups?: {
|
||||||
|
fieldMetadataId: string;
|
||||||
|
isVisible: boolean;
|
||||||
|
fieldValue: string;
|
||||||
|
position: number;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ export const opportunitiesByStageView = (
|
|||||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].id,
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].id,
|
||||||
type: 'kanban',
|
type: 'kanban',
|
||||||
key: null,
|
key: null,
|
||||||
position: 1,
|
position: 2,
|
||||||
icon: 'IconLayoutKanban',
|
icon: 'IconLayoutKanban',
|
||||||
kanbanFieldMetadataId:
|
kanbanFieldMetadataId:
|
||||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].fields[
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].fields[
|
||||||
|
|||||||
@ -0,0 +1,115 @@
|
|||||||
|
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||||
|
|
||||||
|
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||||
|
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||||
|
|
||||||
|
export const opportunitiesTableByStageView = (
|
||||||
|
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
name: 'By Stage',
|
||||||
|
objectMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].id,
|
||||||
|
type: 'table',
|
||||||
|
key: null,
|
||||||
|
position: 1,
|
||||||
|
icon: 'IconList',
|
||||||
|
kanbanFieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].fields[
|
||||||
|
OPPORTUNITY_STANDARD_FIELD_IDS.stage
|
||||||
|
],
|
||||||
|
filters: [],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.name],
|
||||||
|
position: 0,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.amount],
|
||||||
|
position: 1,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.createdBy],
|
||||||
|
position: 2,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.closeDate],
|
||||||
|
position: 3,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.company],
|
||||||
|
position: 4,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact],
|
||||||
|
position: 5,
|
||||||
|
isVisible: true,
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||||
|
isVisible: true,
|
||||||
|
fieldValue: 'NEW',
|
||||||
|
position: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||||
|
isVisible: true,
|
||||||
|
fieldValue: 'SCREENING',
|
||||||
|
position: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||||
|
isVisible: true,
|
||||||
|
fieldValue: 'MEETING',
|
||||||
|
position: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||||
|
isVisible: true,
|
||||||
|
fieldValue: 'PROPOSAL',
|
||||||
|
position: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId:
|
||||||
|
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||||
|
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||||
|
isVisible: true,
|
||||||
|
fieldValue: 'CUSTOMER',
|
||||||
|
position: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -16,7 +16,7 @@ export enum TooltipDelay {
|
|||||||
mediumDelay = '500ms',
|
mediumDelay = '500ms',
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledAppTooltip = styled(Tooltip)`
|
const StyledAppTooltip = styled(Tooltip)<{ width?: string }>`
|
||||||
backdrop-filter: ${({ theme }) => theme.blur.strong};
|
backdrop-filter: ${({ theme }) => theme.blur.strong};
|
||||||
background-color: ${({ theme }) => RGBA(theme.color.gray80, 0.8)};
|
background-color: ${({ theme }) => RGBA(theme.color.gray80, 0.8)};
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
@ -27,7 +27,7 @@ const StyledAppTooltip = styled(Tooltip)`
|
|||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
|
|
||||||
max-width: 40%;
|
max-width: ${({ width }) => width || '40%'};
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
padding: ${({ theme }) => theme.spacing(2)};
|
||||||
@ -49,6 +49,7 @@ export type AppTooltipProps = {
|
|||||||
delay?: TooltipDelay;
|
delay?: TooltipDelay;
|
||||||
positionStrategy?: PositionStrategy;
|
positionStrategy?: PositionStrategy;
|
||||||
clickable?: boolean;
|
clickable?: boolean;
|
||||||
|
width?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppTooltip = ({
|
export const AppTooltip = ({
|
||||||
@ -63,6 +64,7 @@ export const AppTooltip = ({
|
|||||||
positionStrategy,
|
positionStrategy,
|
||||||
children,
|
children,
|
||||||
clickable,
|
clickable,
|
||||||
|
width,
|
||||||
}: AppTooltipProps) => {
|
}: AppTooltipProps) => {
|
||||||
const delayInMs =
|
const delayInMs =
|
||||||
delay === TooltipDelay.noDelay
|
delay === TooltipDelay.noDelay
|
||||||
@ -86,6 +88,7 @@ export const AppTooltip = ({
|
|||||||
positionStrategy,
|
positionStrategy,
|
||||||
children,
|
children,
|
||||||
clickable,
|
clickable,
|
||||||
|
width,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -102,6 +102,48 @@ export const Hoverable: Story = {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const WithWidth: Story = {
|
||||||
|
args: {
|
||||||
|
place: TooltipPosition.Top,
|
||||||
|
delay: TooltipDelay.mediumDelay,
|
||||||
|
content: 'Tooltip with custom width',
|
||||||
|
hidden: false,
|
||||||
|
anchorSelect: '#width-text',
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
render: ({
|
||||||
|
anchorSelect,
|
||||||
|
className,
|
||||||
|
content,
|
||||||
|
delay,
|
||||||
|
noArrow,
|
||||||
|
offset,
|
||||||
|
place,
|
||||||
|
positionStrategy,
|
||||||
|
width,
|
||||||
|
}) => (
|
||||||
|
<>
|
||||||
|
<p id="width-text" data-testid="tooltip">
|
||||||
|
Hover me to see custom width!
|
||||||
|
</p>
|
||||||
|
<Tooltip
|
||||||
|
{...{
|
||||||
|
anchorSelect,
|
||||||
|
className,
|
||||||
|
content,
|
||||||
|
delay,
|
||||||
|
noArrow,
|
||||||
|
offset,
|
||||||
|
place,
|
||||||
|
positionStrategy,
|
||||||
|
width,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
export const Catalog: CatalogStory<Story, typeof Tooltip> = {
|
export const Catalog: CatalogStory<Story, typeof Tooltip> = {
|
||||||
args: { hidden: false, content: 'Tooltip Test' },
|
args: { hidden: false, content: 'Tooltip Test' },
|
||||||
play: async ({ canvasElement }) => {
|
play: async ({ canvasElement }) => {
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export type MenuItemProps = {
|
|||||||
onMouseEnter?: (event: MouseEvent<HTMLDivElement>) => void;
|
onMouseEnter?: (event: MouseEvent<HTMLDivElement>) => void;
|
||||||
onMouseLeave?: (event: MouseEvent<HTMLDivElement>) => void;
|
onMouseLeave?: (event: MouseEvent<HTMLDivElement>) => void;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
|
disabled?: boolean;
|
||||||
text: ReactNode;
|
text: ReactNode;
|
||||||
contextualText?: ReactNode;
|
contextualText?: ReactNode;
|
||||||
hasSubMenu?: boolean;
|
hasSubMenu?: boolean;
|
||||||
@ -49,6 +50,7 @@ export const MenuItem = ({
|
|||||||
text,
|
text,
|
||||||
contextualText,
|
contextualText,
|
||||||
hasSubMenu = false,
|
hasSubMenu = false,
|
||||||
|
disabled = false,
|
||||||
}: MenuItemProps) => {
|
}: MenuItemProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
|
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
|
||||||
@ -64,7 +66,8 @@ export const MenuItem = ({
|
|||||||
return (
|
return (
|
||||||
<StyledHoverableMenuItemBase
|
<StyledHoverableMenuItemBase
|
||||||
data-testid={testId ?? undefined}
|
data-testid={testId ?? undefined}
|
||||||
onClick={handleMenuItemClick}
|
onClick={disabled ? undefined : handleMenuItemClick}
|
||||||
|
disabled={disabled}
|
||||||
className={className}
|
className={className}
|
||||||
accent={accent}
|
accent={accent}
|
||||||
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
|
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
|
||||||
|
|||||||
@ -100,6 +100,11 @@ export const Catalog: CatalogStory<Story, typeof MenuItem> = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'disabled',
|
||||||
|
values: [true, false],
|
||||||
|
props: (disabled: boolean) => ({ disabled }),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
elementContainer: {
|
elementContainer: {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { isUndefined } from '@sniptt/guards';
|
||||||
import { HOVER_BACKGROUND } from '@ui/theme';
|
import { HOVER_BACKGROUND } from '@ui/theme';
|
||||||
import { MenuItemAccent } from '../../types/MenuItemAccent';
|
import { MenuItemAccent } from '../../types/MenuItemAccent';
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ export type MenuItemBaseProps = {
|
|||||||
isKeySelected?: boolean;
|
isKeySelected?: boolean;
|
||||||
isHoverBackgroundDisabled?: boolean;
|
isHoverBackgroundDisabled?: boolean;
|
||||||
hovered?: boolean;
|
hovered?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
|
export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
|
||||||
@ -35,10 +37,16 @@ export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
|
|||||||
${({ theme, isKeySelected }) =>
|
${({ theme, isKeySelected }) =>
|
||||||
isKeySelected ? `background: ${theme.background.transparent.light};` : ''}
|
isKeySelected ? `background: ${theme.background.transparent.light};` : ''}
|
||||||
|
|
||||||
${({ isHoverBackgroundDisabled }) =>
|
${({ isHoverBackgroundDisabled, disabled }) =>
|
||||||
isHoverBackgroundDisabled ?? HOVER_BACKGROUND};
|
(disabled || isHoverBackgroundDisabled) ?? HOVER_BACKGROUND};
|
||||||
|
|
||||||
|
${({ theme, accent, disabled }) => {
|
||||||
|
if (isUndefined(disabled) && disabled !== false) {
|
||||||
|
return css`
|
||||||
|
opacity: 0.4;
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
${({ theme, accent }) => {
|
|
||||||
switch (accent) {
|
switch (accent) {
|
||||||
case 'danger': {
|
case 'danger': {
|
||||||
return css`
|
return css`
|
||||||
@ -112,6 +120,7 @@ export const StyledDraggableItem = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{
|
export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{
|
||||||
|
disabled?: boolean;
|
||||||
isIconDisplayedOnHoverOnly?: boolean;
|
isIconDisplayedOnHoverOnly?: boolean;
|
||||||
cursor?: 'drag' | 'default' | 'not-allowed';
|
cursor?: 'drag' | 'default' | 'not-allowed';
|
||||||
}>`
|
}>`
|
||||||
@ -136,7 +145,11 @@ export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{
|
|||||||
transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease;
|
transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor: ${({ cursor }) => {
|
cursor: ${({ cursor, disabled }) => {
|
||||||
|
if (!isUndefined(disabled) && disabled !== false) {
|
||||||
|
return 'not-allowed';
|
||||||
|
}
|
||||||
|
|
||||||
switch (cursor) {
|
switch (cursor) {
|
||||||
case 'drag':
|
case 'drag':
|
||||||
return 'grab';
|
return 'grab';
|
||||||
|
|||||||
Reference in New Issue
Block a user