Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project labels #181

Merged
merged 76 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
421fdd7
Fix project-label query
oliverroick Jan 5, 2024
d057002
Add update label
oliverroick Jan 9, 2024
a44c3d2
Add create label
oliverroick Jan 9, 2024
f41ff8f
Add manage-label role
oliverroick Jan 10, 2024
e1e9e45
Add color randomizer
oliverroick Jan 10, 2024
eaa115d
Add label preview
oliverroick Jan 10, 2024
282d354
Refactor components
oliverroick Jan 10, 2024
fc36307
Add reload icon
oliverroick Jan 10, 2024
9a0bd80
Select labels from available labels
oliverroick Jan 12, 2024
fa5107c
Add LabelPill component, with color management
oliverroick Jan 17, 2024
d2ed7e9
Fix label form styling
oliverroick Jan 17, 2024
09ca31f
Revert createLabels change
oliverroick Jan 17, 2024
f62a87e
Remove selectLabels selector
oliverroick Jan 17, 2024
ca8952d
Cleanup
oliverroick Jan 17, 2024
189e45d
Fix display color of object labels
oliverroick Jan 18, 2024
5a3c82d
Move contrasting text color function to utils
nathanielrindlaub Jan 21, 2024
20c69c7
Prevent users from creating new categories from category selector
nathanielrindlaub Jan 21, 2024
7711be0
Small stying changes to label editing form
nathanielrindlaub Jan 21, 2024
7f2ab28
Small styling updates
nathanielrindlaub Jan 21, 2024
250da96
Fix bounding box color for new objects
oliverroick Jan 21, 2024
e23da87
Sort label display
oliverroick Jan 22, 2024
2081176
Move update-label actions, reducers to filter slice
oliverroick Jan 22, 2024
b893aeb
Clear images before toggling to new project
nathanielrindlaub Jan 23, 2024
875e974
Revert "Fix bounding box color for new objects"
nathanielrindlaub Jan 23, 2024
9ee262e
Revert "Clear images before toggling to new project"
nathanielrindlaub Jan 23, 2024
e7e3c11
Fix random color generation
oliverroick Jan 23, 2024
1cb8b8c
Clear images before toggling to new project
nathanielrindlaub Jan 23, 2024
db0bb1b
Add color validation
oliverroick Jan 23, 2024
9b4ae82
Merge remote-tracking branch 'origin/project-labels' into project-labels
oliverroick Jan 23, 2024
8f0bcee
Return default text color if bgcolor is not set
oliverroick Jan 24, 2024
35f2ab8
Fix indent
oliverroick Jan 24, 2024
6379b30
Do not clear users on modal close
oliverroick Jan 24, 2024
eced8c4
Rename user role
oliverroick Jan 25, 2024
549dcc3
Sort labels alphbetically
oliverroick Jan 25, 2024
55d9c59
Add label error handling
oliverroick Jan 25, 2024
7455b61
Add default colors picker
nathanielrindlaub Jan 25, 2024
09dc32d
Fix default bbox color
oliverroick Jan 25, 2024
c7e250a
Add unique label name validation
oliverroick Jan 25, 2024
21280d2
Merge remote-tracking branch 'origin/project-labels' into project-labels
oliverroick Jan 25, 2024
612df30
Fix edit label validation
nathanielrindlaub Jan 25, 2024
dbcef68
Make alphabetical label sorting case-insensitive
nathanielrindlaub Jan 25, 2024
8d7feec
Make new label form validation case insensitive
nathanielrindlaub Jan 25, 2024
732ec53
Reset new label form after submission
nathanielrindlaub Jan 25, 2024
0d36f0a
Remove old fetchLabels code
nathanielrindlaub Jan 25, 2024
ccc5db1
Move project label state to projects slice
nathanielrindlaub Jan 26, 2024
72bf24b
Label pill styling update
nathanielrindlaub Jan 26, 2024
f95d612
Add 'none' option to label filters
nathanielrindlaub Jan 26, 2024
bd17b1e
Build out delete label UI
nathanielrindlaub Jan 26, 2024
ff5662a
Wire up UI for disabling/enabling labels
nathanielrindlaub Jan 26, 2024
292fb16
Suppress disabled labels from category selector
nathanielrindlaub Jan 27, 2024
ddf3032
Enable new labels by default
nathanielrindlaub Jan 30, 2024
e6668a8
Add disabled indicator to Label rows
nathanielrindlaub Jan 30, 2024
3b92e06
Fix label loading state tracking
nathanielrindlaub Jan 30, 2024
af4e15d
Add info icon explaining what enabling/disabling labels does
nathanielrindlaub Jan 30, 2024
5e1175f
Wire up deleteProjectLabels requests
nathanielrindlaub Feb 2, 2024
0c14d4f
Clear images after successfully deleting project label
nathanielrindlaub Feb 2, 2024
0bd361f
Add grayscale options to default label colors palette
nathanielrindlaub Feb 3, 2024
28d98e8
Fix redundant default label filters
nathanielrindlaub Feb 6, 2024
c3ce6da
Set minimum label pill height
nathanielrindlaub Feb 6, 2024
ff06c44
Prevent the use of special characters in label names
nathanielrindlaub Feb 6, 2024
3fcf5af
Prevent deletion of default labels
nathanielrindlaub Feb 6, 2024
9ad9fdc
Fix reseting edit label form
nathanielrindlaub Feb 6, 2024
178ce0f
Prevent users from editing default label names
nathanielrindlaub Feb 6, 2024
f3365ac
Generate new random color each time new label form is shown
nathanielrindlaub Feb 7, 2024
3c70cf8
Make available filter state shape uniform
nathanielrindlaub Feb 8, 2024
2e118e6
Use Projects.labels as source of truth for labels state
nathanielrindlaub Feb 8, 2024
28bb9ca
Update addLabels calls
nathanielrindlaub Feb 8, 2024
58e4a49
Fix deleteLabel request
nathanielrindlaub Feb 8, 2024
2984e99
Fix refresh project bug
nathanielrindlaub Feb 8, 2024
47d6a69
Fix mark-empty
nathanielrindlaub Feb 8, 2024
ce4afdb
Pull images from production s3 bucket (temporary test)
nathanielrindlaub Feb 13, 2024
105d125
Allow apostrophes in label names
nathanielrindlaub Feb 14, 2024
c827877
Update delete label alert text
nathanielrindlaub Feb 15, 2024
08f098c
Support lowercase letters in color hex codes
nathanielrindlaub Feb 15, 2024
b45912d
Remove use of labels.source; misc. styling fixes
nathanielrindlaub Feb 16, 2024
8f51ebb
Merge branch 'main' into project-labels
nathanielrindlaub Feb 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9,406 changes: 5,760 additions & 3,646 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@radix-ui/react-navigation-menu": "^1.1.3",
"@radix-ui/react-progress": "^1.0.3",
"@radix-ui/react-scroll-area": "^1.0.4",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-toast": "^1.1.4",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.6",
Expand Down
52 changes: 48 additions & 4 deletions src/api/buildQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ const imageCommentFields = `
const labelFields = `
_id
type
category
conf
bbox
labeledDate
labelId
validation {
validated
validationDate
Expand Down Expand Up @@ -144,6 +144,13 @@ const automationRuleFields = `
}
`;

const projectLabelFields = `
_id
name
color
reviewerEnabled
`;

const projectFields = `
_id
name
Expand All @@ -159,7 +166,7 @@ const projectFields = `
${cameraConfigFields}
}
labels {
categories
${projectLabelFields}
}
availableMLModels
`
Expand Down Expand Up @@ -471,15 +478,52 @@ const queries = {

deleteLabels: (input) => ({
template: `
mutation CreateLabels($input: CreateLabelsInput!) {
createLabels(input: $input) {
mutation DeleteLabels($input: DeleteLabelsInput!) {
deleteLabels(input: $input) {
isOk
}
}
`,
variables: { input: input },
}),

createProjectLabel: (input) => ({
template: `
mutation CreateProjectLabel($input: CreateProjectLabelInput!) {
createProjectLabel(input: $input) {
label {
${projectLabelFields}
}
}
}
`,
variables: { input: input },
}),

updateProjectLabel: (input) => ({
template: `
mutation UpdateProjectLabel($input: UpdateProjectLabelInput!) {
updateProjectLabel(input: $input) {
label {
${projectLabelFields}
}
}
}
`,
variables: { input: input },
}),

deleteProjectLabel: (input) => ({
template: `
mutation DeleteProjectLabel($input: DeleteProjectLabelInput!) {
deleteProjectLabel(input: $input) {
message
}
}
`,
variables: { input: input },
}),

createImageComment: (input) => ({
template: `
mutation CreateImageComment($input: CreateImageCommentInput!){
Expand Down
27 changes: 27 additions & 0 deletions src/app/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,30 @@ export const inViewportTopHalf = (domElement) => {
const elVerticalCenter = rect.top + rect.height / 2;
return elVerticalCenter < viewportEquator;
};

/*
* returns a text color with high contrast relative to a given background color
*/
export const getTextColor = (bgColor) => {
if (!bgColor) {
return '$textDark';
}

const threshold = 0.6
const [red, green, blue] = [0, 2, 4].map((i) => parseInt(bgColor.slice(i + 1, i + 3), 16));
const l = (red * 0.299 + green * 0.587 + blue * 0.114) / 255;
return l < threshold ? '$loContrast' : '$textDark';
};

export const getRandomColor = () => {
const red = Math.floor(Math.random() * (255 - 0) + 0);
const green = Math.floor(Math.random() * (255 - 0) + 0);
const blue = Math.floor(Math.random() * (255 - 0) + 0);

const integer = ((Math.round(red) & 0xFF) << 16)
+ ((Math.round(green) & 0xFF) << 8)
+ (Math.round(blue) & 0xFF);

const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
}
8 changes: 6 additions & 2 deletions src/assets/fontawesome.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import {
faSync,
faExclamation,
faUpload,
faUser
faUser,
faTag,
faRetweet
} from '@fortawesome/free-solid-svg-icons';

library.add(
Expand Down Expand Up @@ -58,5 +60,7 @@ library.add(
faSync,
faExclamation,
faUpload,
faUser
faUser,
faTag,
faRetweet
);
1 change: 1 addition & 0 deletions src/components/AlertDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const AlertDialogContent = styled(AD.AlertDialogContent, {

const AlertDialogTitle = styled(AD.AlertDialogTitle, {
margin: 0,
marginBottom: '$3',
color: '$textDark', //mauve.mauve12,
fontSize: '17px',
fontWeight: '500',
Expand Down
2 changes: 1 addition & 1 deletion src/components/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,4 @@ const Button = styled('button', {
},
});

export default Button;
export default Button;
20 changes: 10 additions & 10 deletions src/components/CategorySelector.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { forwardRef } from 'react';
import { styled } from '../theme/stitches.config.js';
import { useSelector, useDispatch } from 'react-redux';
import CreatableSelect from 'react-select/creatable';
import Select from 'react-select';
import { createFilter } from 'react-select';
import { selectAvailLabels } from '../features/filters/filtersSlice.js';
import { selectSelectedProject, selectProjectLabelsLoading } from '../features/projects/projectsSlice.js';
import { addLabelEnd } from '../features/loupe/loupeSlice.js';


const StyledCategorySelector = styled(CreatableSelect, {
const StyledCategorySelector = styled(Select, {
width: '155px',
fontFamily: '$mono',
fontSize: '$2',
Expand Down Expand Up @@ -66,9 +66,10 @@ const CategorySelector = forwardRef(({
}, ref) => {

// update selector options when new labels become available
const createOption = (category) => ({ value: category.toLowerCase(), label: category });
const availLabels = useSelector(selectAvailLabels);
const options = availLabels.ids.map((id) => createOption(id));
const labelsLoading = useSelector(selectProjectLabelsLoading);
const createOption = (category) => ({ value: category._id, label: category.name });
const enabledLabels = useSelector(selectSelectedProject).labels.filter((lbl) => lbl.reviewerEnabled );
const options = enabledLabels.map(createOption);
const dispatch = useDispatch();

const defaultHandleBlur = (e) => dispatch(addLabelEnd());
Expand All @@ -85,14 +86,13 @@ const CategorySelector = forwardRef(({
classNamePrefix='react-select'
menuPlacement={menuPlacement}
filterOption={createFilter({ matchFrom: 'start' })}
isLoading={availLabels.isLoading}
isDisabled={availLabels.isLoading}
isLoading={labelsLoading.isLoading}
isDisabled={labelsLoading.isLoading}
onChange={handleCategoryChange}
onCreateOption={handleCategoryChange}
onBlur={handleCategorySelectorBlur || defaultHandleBlur}
options={options}
/>
);
});

export default CategorySelector;
export default CategorySelector;
4 changes: 4 additions & 0 deletions src/components/ErrorAlerts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
} from '../features/upload/uploadSlice';
import getErrorContent from '../content/Errors';
import { selectManageUserErrors, dismissManageUsersError } from '../features/projects/usersSlice';
import { selectManageLabelsErrors, dismissManageLabelsError } from '../features/projects/projectsSlice';

// TODO: add updateAutomationRules errors

Expand All @@ -69,6 +70,7 @@ const ErrorAlerts = () => {
const redriveBatchErrors = useSelector(selectRedriveBatchErrors);
const manageUserErrors = useSelector(selectManageUserErrors);
const createProjectErrors = useSelector(selectCreateProjectsErrors);
const manageLabelsErrors = useSelector(selectManageLabelsErrors);

const enrichedErrors = [
enrichErrors(labelsErrors, 'Label Error', 'labels'),
Expand All @@ -86,6 +88,7 @@ const ErrorAlerts = () => {
enrichErrors(redriveBatchErrors, 'Error retrying failed images in batch', 'redriveBatch'),
enrichErrors(manageUserErrors, 'Manage user error', 'manageUsers'),
enrichErrors(createProjectErrors, 'Error Creating Project', 'createProject'),
enrichErrors(manageLabelsErrors, 'Error Updating Label', 'manageLabels'),
];

const errors = enrichedErrors.reduce((acc, curr) => (
Expand Down Expand Up @@ -147,6 +150,7 @@ const dismissErrorActions = {
'uploadImageErrors': (i) => dismissExportErrorsError(i),
'redriveBatch': (i) => dismissRedriveBatchError(i),
'manageUsers': (i) => dismissManageUsersError(i),
'manageLabels': (i) => dismissManageLabelsError(i),
};

function enrichErrors(errors, title, entity) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const textInput = {
transition: 'all 0.2s ease',
outline: 'none',
boxShadow: '0 0 0 3px $gray3',
borderColor: '$textDark',
// borderColor: '$textDark',
'&:hover': {
boxShadow: '0 0 0 3px $blue200',
borderColor: '$blue500',
Expand Down
7 changes: 7 additions & 0 deletions src/components/HydratedModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import AutomationRulesForm from '../features/projects/AutomationRulesForm.jsx';
import SaveViewForm from '../features/projects/SaveViewForm.jsx';
import DeleteViewForm from '../features/projects/DeleteViewForm.jsx';
import ManageUsersModal from '../features/projects/ManageUsersModal.jsx';
import ManageLabelsModal from '../features/projects/ManageLabelsModal/index.jsx';
import BulkUploadForm from '../features/upload/BulkUploadForm.jsx';
import { clearExport, clearStats } from '../features/images/imagesSlice';
import { clearErrorsExport } from '../features/upload/uploadSlice.js'
Expand Down Expand Up @@ -78,6 +79,12 @@ const HydratedModal = () => {
content: <ManageUsersModal/>,
callBackOnClose: () => dispatch(clearUsers()),
},
'manage-labels-form': {
title: 'Manage labels',
size: 'md',
content: <ManageLabelsModal/>,
callBackOnClose: () => true,
},
};

const handleModalToggle = (content) => {
Expand Down
43 changes: 43 additions & 0 deletions src/components/LabelPill.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { styled } from '../theme/stitches.config.js';
import { getTextColor } from '../app/utils.js';

const Pill = styled('div', {
fontSize: '$2',
fontWeight: '$5',
fontFamily: '$mono',
padding: '$1 $3',
'&:not(:last-child)': {
marginRight: '$2',
},
minHeight: '28px',
borderRadius: '$3',
border: '1px solid rgba(0,0,0,0)',
transition: 'all 0.2s ease',
variants: {
focused: {
true: {
outline: 'none',
boxShadow: '0 0 0 3px $blue200',
borderColor: '$blue500',
}
}
}
});

const LabelPill = ({ color, name, css, ...props }) => {
return (
<Pill
css={{
backgroundColor: `${color}1A`,
borderColor: color,
color: '$textDark', // getTextColor(color),
...css
}}
{...props}
>
{name}
</Pill>
);
}

export default LabelPill;
4 changes: 3 additions & 1 deletion src/components/SelectField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ const SelectField = ({
error,
touched,
isSearchable,
isMulti
isMulti,
menuPlacement='bottom'
}) => {

const handleChange = (value) => {
Expand All @@ -87,6 +88,7 @@ const SelectField = ({
classNamePrefix='react-select'
isSearchable={isSearchable}
isMulti={isMulti}
menuPlacement={menuPlacement}
/>
{!!error &&
touched && (
Expand Down
40 changes: 40 additions & 0 deletions src/components/Switch.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as Switch from '@radix-ui/react-switch';
import { styled } from '../theme/stitches.config.js';
import { blackA } from '@radix-ui/colors';

export const SwitchRoot = styled(Switch.Root, {
all: 'unset',
width: 42,
height: 25,
backgroundColor: blackA.blackA6,
borderRadius: '9999px',
position: 'relative',
// boxShadow: `0 2px 10px ${blackA.blackA4}`,
border: '1px solid',
borderColor: '$border',
WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)',
'&:focus': {
transition: 'all 0.2s ease',
outline: 'none',
boxShadow: '0 0 0 3px $gray3',
// borderColor: '$textDark',
'&:hover': {
boxShadow: '0 0 0 3px $blue200',
borderColor: '$blue500',
},
},
'&[data-state="checked"]': { backgroundColor: 'black' },
});

export const SwitchThumb = styled(Switch.Thumb, {
display: 'block',
width: 21,
height: 21,
backgroundColor: 'white',
borderRadius: '9999px',
boxShadow: `0 2px 2px ${blackA.blackA4}`,
transition: 'transform 100ms',
transform: 'translateX(2px)',
willChange: 'transform',
'&[data-state="checked"]': { transform: 'translateX(19px)' },
});
4 changes: 4 additions & 0 deletions src/components/Tooltip.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { styled, keyframes } from '@stitches/react';
// import { PlusIcon } from '@radix-ui/react-icons';
// import { violet, blackA } from '@radix-ui/colors';
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import { blue } from '@radix-ui/colors';

const slideUpAndFade = keyframes({
'0%': { opacity: 0, transform: 'translateY(2px)' },
Expand Down Expand Up @@ -32,6 +33,9 @@ const StyledContent = styled(TooltipPrimitive.Content, {
color: '$loContrast',
backgroundColor: '$hiContrast',
boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px',
'a': {
color: blue.blue9,
},
'@media (prefers-reduced-motion: no-preference)': {
animationDuration: '400ms',
animationTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)',
Expand Down
Loading
Loading