Skip to content

Commit

Permalink
feat: StyledSchemaFormInPlace schema component
Browse files Browse the repository at this point in the history
  • Loading branch information
olzzon committed Nov 13, 2024
1 parent 6a10475 commit 61c73a0
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 10 deletions.
2 changes: 1 addition & 1 deletion packages/webui/src/client/lib/Components/DropdownInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export function DropdownInputControl<TValue>({
const newOptions = [
...options,
{
name: 'Value: ' + value,
name: String(value),
value: value,
i: options.length,
},
Expand Down
76 changes: 76 additions & 0 deletions packages/webui/src/client/lib/forms/SchemaFormInPlace.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// This styling has a lot of force added, and should be seen as a workaround
// to get styling on the current Sofie UI schema/overrides components
// without changing current look and behavior in other places of Sofie
.styled-schema-form {
width: 100%;

// Force the base input-l class
.input-l {
width: 100% !important;
max-width: none !important;
margin-left: 0px;
border: none;
}

// Force the select/text-input defaults
.select,
.inline-select,
.text-input {
display: block !important;
position: relative;
width: 100% !important;
}

.input {
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
padding: 0.5rem 0.75rem;
width: 100%;

&:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 1px #3b82f6;
}
}

.label-text {
&:before {
content: none !important;
}
}

.dropdown {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
width: 100%;
max-width: 100%;

.input,
.input-l {
border: none;
outline: none;
box-shadow: none;
}

&:focus-within {
border-color: #3b82f6;
box-shadow: 0 0 0 1px #3b82f6;
}
}

// Force the label over selector
.label-actual {
margin-bottom: 0.5rem !important; // Increased spacing between label and selector
}

.label {
font-size: 0.875rem;
font-weight: 500;
color: #374151;
display: block;
}


}
53 changes: 53 additions & 0 deletions packages/webui/src/client/lib/forms/SchemaFormInPlace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '../../ui/Settings/util/OverrideOpHelper'
import { SchemaFormCommonProps } from './schemaFormUtil'
import { SchemaFormWithOverrides } from './SchemaFormWithOverrides'
import './SchemaFormInPlace.scss'

interface SchemaFormInPlaceProps extends Omit<SchemaFormCommonProps, 'isRequired'> {
/** The object to be modified in place */
Expand Down Expand Up @@ -33,6 +34,58 @@ export function SchemaFormInPlace({ object, ...commonProps }: Readonly<SchemaFor
return <SchemaFormWithOverrides {...commonProps} attr={''} item={wrappedItem} overrideHelper={helper} isRequired />
}

interface StyledSchemaFormInPlaceProps extends Omit<SchemaFormCommonProps, 'isRequired'> {
/** The object to be modified in place */
object: any
/** Optional CSS class to apply to the form wrapper */
/** This may or may not work, as there's different styling in the sub components */
className?: string
/** Whether to use compact styling */
compact?: boolean
/** Width for the form (e.g., '300px', '100%') */
width?: string
}

export function StyledSchemaFormInPlace({
object,
className = '',
compact = false,
width = '',
...commonProps
}: Readonly<StyledSchemaFormInPlaceProps>): JSX.Element {
// This is a hack to avoid issues with the UI re-rendering as 'nothing' changed
const [editCount, setEditCount] = useState(0)
const forceRender = useCallback(() => setEditCount((v) => v + 1), [])

const helper = useCallback(() => new OverrideOpHelperInPlace(object, forceRender), [object, forceRender])

const wrappedItem = useMemo(
() =>
literal<WrappedOverridableItemNormal<any>>({
type: 'normal',
id: 'not-used' + editCount,
computed: object,
defaults: undefined,
overrideOps: [],
}),
[object, editCount]
)

const style = {
width: width || '300px',
maxWidth: width || '300px',
minWidth: width || '300px',
}

const formClasses = ['styled-schema-form', compact ? 'space-y-2' : 'space-y-4', className].filter(Boolean).join(' ')

return (
<div className={formClasses} style={style}>
<SchemaFormWithOverrides {...commonProps} attr={''} item={wrappedItem} overrideHelper={helper} isRequired />
</div>
)
}

/**
* An alternate OverrideOpHelper designed to directly mutate an object, instead of using the `ObjectWithOverrides` system.
* This allows us to have one SchemaForm implementation that can handle working with `ObjectWithOverrides`, and simpler options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ interface FormComponentProps {

function useChildPropsForFormComponent(props: Readonly<SchemaFormWithOverridesProps>): FormComponentProps {
return useMemo(() => {
const title = getSchemaUIField(props.schema, SchemaFormUIField.Title) || props.attr
// If a tittle is added to the Schema use that if not use the props.attr instead
const title = props.schema.title || getSchemaUIField(props.schema, SchemaFormUIField.Title) || props.attr
const description = getSchemaUIField(props.schema, SchemaFormUIField.Description)

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { useSelection } from '../RundownView/SelectedElementsContext'
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
import { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part'
import { RundownId } from '@sofie-automation/corelib/dist/dataModel/Ids'
import { SchemaFormInPlace } from '../../lib/forms/SchemaFormInPlace'
import { StyledSchemaFormInPlace } from '../../lib/forms/SchemaFormInPlace'
import { RundownUtils } from '../../lib/rundown'
import * as CoreIcon from '@nrk/core-icons/jsx'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
Expand Down Expand Up @@ -453,12 +453,6 @@ function EditingTypeChangeSourceLayerSource(props: {
getPendingState() !== undefined && getPendingState() !== props.userEditOperation.currentValues.value
)

React.useEffect(() => {
setHasBeenEdited(
getPendingState() !== undefined && getPendingState() !== props.userEditOperation.currentValues.value
)
}, [props.userEditOperation.id, props.pendingChanges])

const jsonSchema = Object.values<UserEditingSourceLayer>(props.userEditOperation.schemas).find(
(layer) => layer.sourceLayerType === selectedSourceGroup
)?.schema
Expand All @@ -470,6 +464,10 @@ function EditingTypeChangeSourceLayerSource(props: {
setSelectedSourceButton(pendingChange?.sourceLayerType || props.userEditOperation.currentValues.type)

setSelectedValues(pendingChange?.value || props.userEditOperation.currentValues.value)

setHasBeenEdited(
getPendingState() !== undefined && getPendingState() !== props.userEditOperation.currentValues.value
)
}, [props.userEditOperation.id, props.pendingChanges])

const handleSourceChange = () => {
Expand Down Expand Up @@ -541,10 +539,13 @@ function EditingTypeChangeSourceLayerSource(props: {
onChange={handleSourceChange}
>
{hasBeenEdited && <FontAwesomeIcon icon="pencil-alt" />}
<SchemaFormInPlace
<StyledSchemaFormInPlace
schema={selectedGroupSchema}
object={selectedValues}
translationNamespaces={props.userEditOperation.translationNamespaces}
compact={false}
className="custom-class"
width="100%"
/>
</div>
</div>
Expand Down

0 comments on commit 61c73a0

Please sign in to comment.