Skip to content
This repository was archived by the owner on Mar 8, 2024. It is now read-only.

Commit a76cdaa

Browse files
lumburovskalinaJWittmeyerJWittmeyer
authored
Shared component dropdown (#10)
* Kern dropdowns refactor * Add checkboxes option to kern dropdown * Remove unused code * Removed unused code * Kern dropdown improvements for disabled buttons * Removed unused code * Remove commented code * Adds first (unfinished) version of iteration * With icon option * Adds checkbox logic * Replaced dropdown with one component * Removed unused code * Removed unused code * Renamed existing component to kern dropdown * Reverted change * Removed dummy code * Removed commented code * Header zindex over sticky header on heuristics and lookup lists * Console log removed * Improvements on dropdown shared component * Prefilled heuristics * Updated dropdown options * More flexible dropdown * Updated helped with more explanations * Adds differnt logic for color generation * Remove debug values * Width changes * Small fixes on dropdown * Function name changed Co-authored-by: JWittmeyer <jens.wittmeyer@onetask.ai> Co-authored-by: JWittmeyer <91723236+JWittmeyer@users.noreply.github.com>
1 parent 7ee1e9e commit a76cdaa

27 files changed

+1161
-1269
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ testem.log
4444
# System Files
4545
.DS_Store
4646
Thumbs.db
47+
48+
.angular/

src/app/base/base.module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { SidebarPmComponent } from './components/sidebar-pm/sidebar-pm.component
1616
import { DropdownDirective } from './directives/dropdown.directive';
1717
import { PercentRoundPipe } from './pipes/decimal-round.pipe';
1818
import { HeaderComponent } from './components/header/header.component';
19+
import { DropdownComponent } from './components/dropdown/dropdown.component';
1920
import { HeuristicStatusesComponent } from './components/heuristic-statuses/heuristic-statuses.component';
2021

2122
@NgModule({
@@ -28,6 +29,7 @@ import { HeuristicStatusesComponent } from './components/heuristic-statuses/heur
2829
DropdownDirective,
2930
PercentRoundPipe,
3031
HeaderComponent,
32+
DropdownComponent,
3133
HeuristicStatusesComponent
3234
],
3335
imports: [CommonModule, AppRoutingModule, HighlightModule],
@@ -50,6 +52,7 @@ import { HeuristicStatusesComponent } from './components/heuristic-statuses/heur
5052
DropdownDirective,
5153
PercentRoundPipe,
5254
HeaderComponent,
55+
DropdownComponent,
5356
HeuristicStatusesComponent
5457
],
5558
providers: [
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { FormArray } from "@angular/forms";
2+
3+
/**
4+
* Optionset for kern dropdown
5+
* @optionArray {string[] | FormArray[] | any[]} - Can be any array. string array is just used, FormArray or any object array tries to use "name" property then "text" last first string property
6+
* @buttonCaption {string, optional} - used as caption for the button, if not given the first / current value is used
7+
* @valuePropertyPath {string, optional} - if undefined option text is returned, else (e.g. name.tmp.xyz) the path is split and used to access the object property
8+
* @keepDropdownOpen {boolean, optional} - stops the event propagation of the click event and therfore keeps the menu open
9+
* @buttonTooltip {string, optional} - adds a tooltip if defined
10+
* @isDisabled {boolean, optional} - disables the dropdown
11+
* @isOptionDisabled {boolean[], optional} - disables the dropdown option (needs to be the exact same length as the optionArray)
12+
* @optionIcons {string[], optional} - displays a predfined icon if set for the index (needs to be the exact same length as the optionArray)
13+
* @hasCheckboxes {boolean, optional} - helper for checkbox like dropdowns (e.g. data browser)
14+
* @buttonVersion {string, optional} - defaults to 'default' (button with a caption text), '...', 'userIcon'
15+
* @avatarUri {string, optional} - link to the avatar image for logged user
16+
* @prefix {string, optional} - prefix to the main name in the option
17+
* @postfix {string, optional} - postfix to the main name in the option
18+
* @buttonBgColor {string, optional} - background color for the button
19+
* @buttonTextColor {string, optional} - text color for the button
20+
* @optionDescriptions {string, optional} - array with optional descriptions to the options
21+
* @hoverColor {string, optional} - background color on hover for the dropdown options
22+
* @textColor {string, optional} - text color for the dropdown options
23+
* @textHoverColor {string, optional} - text color on hover for the dropdown options
24+
* @textSize {string, optional} - text size for the dropdown options
25+
* @isButtonSampleProjects {boolean, optional} - checks if the button is the specific one for sample project
26+
*/
27+
export type DropdownOptions = {
28+
optionArray: string[] | FormArray[] | any[];
29+
buttonCaption?: string;
30+
valuePropertyPath?: string;
31+
keepDropdownOpen?: boolean;
32+
buttonTooltip?: string;
33+
isDisabled?: boolean;
34+
isOptionDisabled?: boolean[];
35+
optionIcons?: string[];
36+
hasCheckboxes?: boolean;
37+
buttonVersion?: string;
38+
avatarUri?: string;
39+
prefix?: string;
40+
postfix?: string;
41+
buttonBgColor?: string;
42+
buttonTextColor?: string;
43+
optionDescriptions?: string[];
44+
hoverColor?: string;
45+
textColor?: string;
46+
textHoverColor?: string;
47+
textSize?: string;
48+
isButtonSampleProjects?: boolean;
49+
};
50+
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
<div class="relative" [ngClass]="dropdownOptions.buttonVersion == 'default' ? ' w-max' : '' ">
2+
<button #dropdownOpenButton type="button" [attr.data-tip]="dropdownOptions.buttonTooltip" *ngIf="dropdownOptions.buttonVersion == 'default'"
3+
class="inline-flex rounded-md border shadow-sm px-4 items-center text-xs font-semibold cursor-pointer focus:ring-offset-2 focus:ring-offset-gray-400"
4+
id="menu-button" aria-expanded="true" aria-haspopup="true" [disabled]="dropdownOptions.isDisabled"
5+
[ngClass]="buttonClassList" (isMenuOpen)="toggleVisible($event, dropdownOptionsDiv)" appDropdown>
6+
{{ dropdownOptions.hasCheckboxes?'':dropdownOptions.buttonCaption }}
7+
<ng-template [ngIf]="dropdownOptions.hasCheckboxes">
8+
<label class="truncate cursor-pointer">{{getDropdownDisplayText(dropdownOptions.optionArray,"EMPTY")}}
9+
<span style="color:#2563eb">{{getDropdownDisplayText(dropdownOptions.optionArray,"NOT_NEGATED")}}</span>
10+
<span style="color:#ef4444">{{getDropdownDisplayText(dropdownOptions.optionArray,"NEGATED")}}</span>
11+
</label>
12+
</ng-template>
13+
<svg class="-mr-1 ml-auto h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"
14+
aria-hidden="true">
15+
<path fill-rule="evenodd"
16+
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
17+
clip-rule="evenodd" />
18+
</svg>
19+
</button>
20+
21+
<svg *ngIf="dropdownOptions.buttonVersion== '...'" (isMenuOpen)="toggleVisible($event, dropdownOptionsDiv)" appDropdown
22+
xmlns="http://www.w3.org/2000/svg"
23+
class="h-5 w-5 float-right cursor-pointer text-gray-500" viewBox="0 0 20 20"
24+
fill="currentColor">
25+
<path
26+
d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
27+
</svg>
28+
<a *ngIf="dropdownOptions.buttonVersion== 'userIcon'" tabindex="0" class="w-full cursor-pointer">
29+
<div data-intercom-target="User Avatar Button" (isMenuOpen)="toggleVisible($event, dropdownOptionsDiv)" appDropdown>
30+
<img class="h-8 w-8" [src]="dropdownOptions.avatarUri">
31+
</div>
32+
</a>
33+
34+
<div #dropdownOptionsDiv
35+
class="origin-top-right absolute mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none hidden"
36+
[ngClass]="[dropdownClassList, dropdownOptions.isButtonSampleProjects ? 'width-sample-projects' : '', dropdownOptions.buttonVersion != '...' ? 'min-w-full': '']"
37+
role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
38+
<div class="py-1 cursor-pointer" role="none">
39+
<div *ngFor="let caption of dropdownOptionCaptions;let i = index" (click)="performActionOnOption($event,i)"
40+
[ngClass]="[dropdownOptions.textSize,dropdownOptions.textColor,dropdownOptions.optionDescriptions ? '' : 'flex' ,dropdownOptions.isOptionDisabled?.length && dropdownOptions.isOptionDisabled[i]?'opacity-50 cursor-not-allowed':'',!dropdownOptions.hasCheckboxes ? dropdownOptions.hoverColor + ' ' +dropdownOptions.textHoverColor:'']"
41+
[ngStyle]="{'border-bottom': dropdownOptions.isButtonSampleProjects && i%2 == 0 && i!=dropdownOptionCaptions.length-1 ? '1px dashed #e2e8f0' : (dropdownOptions.isButtonSampleProjects && i%2 != 0 && i!=dropdownOptionCaptions.length-1 ? '1px solid #e2e8f0' : null) }"
42+
class="block px-2 py-1.5 flex-row flex-nowrap items-center gap-x-2 w-max min-w-full"
43+
role="menuitem" tabindex="-1" id="menu-item-0">
44+
<ng-template [ngIf]="dropdownOptions.hasCheckboxes">
45+
<div class="h-4 w-4 border-gray-300 border rounded hover:bg-gray-200"
46+
[ngStyle]="{'background-color':getActiveNegateGroupColor(dropdownOptions.optionArray[i]), 'border-color':getActiveNegateGroupColor(dropdownOptions.optionArray[i])}">
47+
</div>
48+
</ng-template>
49+
<ng-template [ngIf]="dropdownOptions.optionIcons?.length">
50+
<ng-container [ngTemplateOutlet]="icons"
51+
[ngTemplateOutletContext]="{iconName:dropdownOptions.optionIcons[i]}">
52+
</ng-container>
53+
</ng-template>
54+
{{ caption }}
55+
56+
<p *ngIf="dropdownOptions.optionDescriptions && dropdownOptions.optionDescriptions[i] != ''" class="mt-2">
57+
{{dropdownOptions.optionDescriptions[i]}}
58+
</p>
59+
</div>
60+
</div>
61+
</div>
62+
</div>
63+
64+
65+
<ng-template #icons let-iconName="iconName">
66+
<ng-container [ngSwitch]="iconName">
67+
<ng-template ngSwitchDefault>
68+
</ng-template>
69+
<ng-template ngSwitchCase="clickbait">
70+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-fish-hook inline-block" width="20"
71+
height="20" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
72+
stroke-linecap="round" stroke-linejoin="round">
73+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
74+
<path d="M16 9v6a5 5 0 0 1 -10 0v-4l3 3"></path>
75+
<circle cx="16" cy="7" r="2"></circle>
76+
<path d="M16 5v-2"></path>
77+
</svg>
78+
</ng-template>
79+
<ng-template ngSwitchCase="conversational-ai">
80+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-message-circle inline-block" width="20"
81+
height="20" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
82+
stroke-linecap="round" stroke-linejoin="round">
83+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
84+
<path d="M3 20l1.3 -3.9a9 8 0 1 1 3.4 2.9l-4.7 1"></path>
85+
<line x1="12" y1="12" x2="12" y2="12.01"></line>
86+
<line x1="8" y1="12" x2="8" y2="12.01"></line>
87+
<line x1="16" y1="12" x2="16" y2="12.01"></line>
88+
</svg>
89+
</ng-template>
90+
<ng-template ngSwitchCase="ag-news">
91+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-news inline-block" width="20" height="20"
92+
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
93+
stroke-linejoin="round">
94+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
95+
<path
96+
d="M16 6h3a1 1 0 0 1 1 1v11a2 2 0 0 1 -4 0v-13a1 1 0 0 0 -1 -1h-10a1 1 0 0 0 -1 1v12a3 3 0 0 0 3 3h11">
97+
</path>
98+
<line x1="8" y1="8" x2="12" y2="8"></line>
99+
<line x1="8" y1="12" x2="12" y2="12"></line>
100+
<line x1="8" y1="16" x2="12" y2="16"></line>
101+
</svg>
102+
</ng-template>
103+
<ng-template ngSwitchCase="select-all">
104+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-square-check inline-block"
105+
width="20" height="20" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
106+
stroke-linecap="round" stroke-linejoin="round">
107+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
108+
<rect x="4" y="4" width="16" height="16" rx="2"></rect>
109+
<path d="M9 12l2 2l4 -4"></path>
110+
</svg>
111+
</ng-template>
112+
<ng-template ngSwitchCase="deselect-all">
113+
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-square inline-block" width="20"
114+
height="20" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
115+
stroke-linecap="round" stroke-linejoin="round">
116+
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
117+
<rect x="4" y="4" width="16" height="16" rx="2"></rect>
118+
</svg>
119+
</ng-template>
120+
<ng-template ngSwitchCase="run">
121+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block" viewBox="0 0 20 20"
122+
fill="currentColor">
123+
<path fill-rule="evenodd"
124+
d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z"
125+
clip-rule="evenodd" />
126+
</svg>
127+
</ng-template>
128+
<ng-template ngSwitchCase="edit-term">
129+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block" viewBox="0 0 20 20"
130+
fill="currentColor">
131+
<path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
132+
<path fill-rule="evenodd"
133+
d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z"
134+
clip-rule="evenodd" />
135+
</svg>
136+
</ng-template>
137+
<ng-template ngSwitchCase="remove-term">
138+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block" viewBox="0 0 20 20"
139+
fill="currentColor">
140+
<path fill-rule="evenodd"
141+
d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z"
142+
clip-rule="evenodd" />
143+
</svg>
144+
</ng-template>
145+
<ng-template ngSwitchCase="whitelist-term">
146+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block" viewBox="0 0 20 20"
147+
fill="currentColor">
148+
<path fill-rule="evenodd"
149+
d="M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
150+
clip-rule="evenodd" />
151+
</svg>
152+
</ng-template>
153+
<ng-template ngSwitchCase="blacklist-term">
154+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block" viewBox="0 0 20 20"
155+
fill="currentColor">
156+
<path fill-rule="evenodd"
157+
d="M10 1.944A11.954 11.954 0 012.166 5C2.056 5.649 2 6.319 2 7c0 5.225 3.34 9.67 8 11.317C14.66 16.67 18 12.225 18 7c0-.682-.057-1.35-.166-2.001A11.954 11.954 0 0110 1.944zM11 14a1 1 0 11-2 0 1 1 0 012 0zm0-7a1 1 0 10-2 0v3a1 1 0 102 0V7z"
158+
clip-rule="evenodd" />
159+
</svg>
160+
</ng-template>
161+
<ng-template ngSwitchCase="delete-selected">
162+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block" fill="none"
163+
viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
164+
<path stroke-linecap="round" stroke-linejoin="round"
165+
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
166+
</svg>
167+
</ng-template>
168+
<ng-template ngSwitchCase="labeling-function">
169+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block"
170+
viewBox="0 0 20 20" fill="currentColor">
171+
<path fill-rule="evenodd"
172+
d="M12.316 3.051a1 1 0 01.633 1.265l-4 12a1 1 0 11-1.898-.632l4-12a1 1 0 011.265-.633zM5.707 6.293a1 1 0 010 1.414L3.414 10l2.293 2.293a1 1 0 11-1.414 1.414l-3-3a1 1 0 010-1.414l3-3a1 1 0 011.414 0zm8.586 0a1 1 0 011.414 0l3 3a1 1 0 010 1.414l-3 3a1 1 0 11-1.414-1.414L16.586 10l-2.293-2.293a1 1 0 010-1.414z"
173+
clip-rule="evenodd" />
174+
</svg>
175+
</ng-template>
176+
177+
<ng-template ngSwitchCase="active-learning">
178+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block"
179+
viewBox="0 0 20 20" fill="currentColor">
180+
<path fill-rule="evenodd"
181+
d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z"
182+
clip-rule="evenodd" />
183+
</svg>
184+
</ng-template>
185+
186+
<ng-template ngSwitchCase="zero-shot">
187+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 inline-block"
188+
viewBox="0 0 20 20" fill="currentColor">
189+
<path fill-rule="evenodd"
190+
d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 110 2H6v1a1 1 0 11-2 0v-1H3a1 1 0 110-2h1v-1a1 1 0 011-1zM12 2a1 1 0 01.967.744L14.146 7.2 17.5 9.134a1 1 0 010 1.732l-3.354 1.935-1.18 4.455a1 1 0 01-1.933 0L9.854 12.8 6.5 10.866a1 1 0 010-1.732l3.354-1.935 1.18-4.455A1 1 0 0112 2z"
191+
clip-rule="evenodd" />
192+
</svg>
193+
</ng-template>
194+
</ng-container>
195+
196+
</ng-template>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.tooltip::before {
2+
z-index: 50;
3+
}
4+
5+
.width-icon-menues {
6+
width: 128px;
7+
}
8+
9+
.width-sample-projects {
10+
width: 384px !important;
11+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { DropdownComponent } from './dropdown.component';
4+
5+
describe('DropdownItComponent', () => {
6+
let component: DropdownComponent;
7+
let fixture: ComponentFixture<DropdownComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [DropdownComponent]
12+
})
13+
.compileComponents();
14+
});
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(DropdownComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});

0 commit comments

Comments
 (0)