Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 18 additions & 2 deletions src/containers/SettingsEditor/FormTemplates/FieldTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { FieldTemplateProps } from '@rjsf/utils'
import { CSS } from 'styled-components/dist/types'
import { matchesFilterKeys } from './searchMatcher'
import { toast } from 'react-toastify'
import AccessWidget from '../Widgets/AccessWidget'

const arrayStartsWith = (arr1: $Any, arr2: $Any) => {
// return true, if first array starts with second array
Expand Down Expand Up @@ -54,8 +55,9 @@ function FieldTemplate(props: FieldTemplateProps) {
}, [section, filterKeys])

// Object fields


if (props.schema.type === 'object') {
if (props.schema.type === 'object' && props.schema?.widget !== 'access') {
return (
<>
{divider}
Expand Down Expand Up @@ -204,6 +206,19 @@ function FieldTemplate(props: FieldTemplateProps) {
props.id,
)


let mainWidget = null
if (props.schema.widget === 'access') {
mainWidget = (
<AccessWidget {...props} />
)
} else {
mainWidget = props.children
}




return (
<div
data-schema-id={props.id}
Expand Down Expand Up @@ -238,7 +253,8 @@ function FieldTemplate(props: FieldTemplateProps) {
</span>
</div>
)}
<div className={`form-inline-field-widget ${widgetClass}`}>{props.children}</div>

<div className={`form-inline-field-widget ${widgetClass}`}>{mainWidget}</div>
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const arrayStartsWith = (arr1: $Any, arr2: $Any) => {
return true
}


function ObjectFieldTemplate(props: { id: string } & ObjectFieldTemplateProps) {
const [contextMenu] = useCreateContextMenu([])
let className = 'form-object-field'
Expand Down Expand Up @@ -78,6 +79,7 @@ function ObjectFieldTemplate(props: { id: string } & ObjectFieldTemplateProps) {
}, [props.properties])

const fields = useMemo(() => {

let hiddenFields: $Any[] = []
for (const propName in props?.schema?.properties || {}) {
//@ts-ignore
Expand All @@ -96,6 +98,7 @@ function ObjectFieldTemplate(props: { id: string } & ObjectFieldTemplateProps) {
}
}


if (props.schema.layout === 'expanded') {
let nameField = null
let otherFields = []
Expand Down Expand Up @@ -162,6 +165,7 @@ function ObjectFieldTemplate(props: { id: string } & ObjectFieldTemplateProps) {

// aaand... render


if (['compact', 'root', 'expanded'].includes(props.schema.layout)) return fields

const contextMenuModel = useMemo(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/containers/SettingsEditor/SettingsEditor.sass
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ $field-gap: 8px

.form-inline-field
display: flex
min-width: 250px
flex-grow: 1
flex-direction: row
align-items: center
Expand All @@ -135,7 +136,6 @@ $field-gap: 8px

.form-inline-field-label
flex-basis: 250px
min-width: 250px
padding-left: 4px
cursor: pointer
user-select: none
Expand Down
45 changes: 43 additions & 2 deletions src/containers/SettingsEditor/SettingsEditor.styled.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from 'styled-components'

const FormWrapper = styled.div<{$currentSelection: string}>`
const FormWrapper = styled.div<{ $currentSelection: string }>`
[data-fieldid='${(props) => props.$currentSelection}'] {
border-radius: 4px;
background-color: rgba(0, 0, 0, 0.2);
Expand Down Expand Up @@ -39,4 +39,45 @@ const FormWrapper = styled.div<{$currentSelection: string}>`
}
}
`
export { FormWrapper }


const CodeEditorWrapper = styled.div`
position: relative;
display: flex;
resize: vertical;
overflow: auto;
flex-direction: column;
min-height: 40px;
height: 200px;
border: 1px solid var(--md-sys-color-outline-variant);
border-radius: var(--border-radius-m);

.wrap {
position: relative;
top: 0;
left: 0;
overflow: scroll;
}
.w-tc-editor {
background-color: var(--md-sys-color-surface-container-low);
flex-grow: 1;
overflow: unset !important;
* {
background-color: var(--md-sys-color-surface-container-low);
font-family: monospace !important;
font-size: 12px;
}
}

&.error {
border: 1px solid var(--md-sys-color-error);
}

&.changed {
border: 1px solid var(--md-sys-color-primary);
}

`


export { FormWrapper, CodeEditorWrapper }
202 changes: 202 additions & 0 deletions src/containers/SettingsEditor/Widgets/AccessWidget.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import axios from 'axios'
import styled from 'styled-components'

import { toast } from 'react-toastify'
import { useState, useEffect, useMemo } from 'react'
import { updateChangedKeys, parseContext, getDefaultValue } from '../helpers'
import CodeEditor from '@uiw/react-textarea-code-editor'
import { CodeEditorWrapper } from '../SettingsEditor.styled'
import { Button, Dialog } from '@ynput/ayon-react-components'


const ShareOption = styled.div`
background: #434a56;
border-radius: 4px;
padding: 8px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
`

const ShareOptionsContainer = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
overflow-y: auto;
`




const AccessEditorDialog = ({ initialValue, onSubmit, projectName }) => {

const [shareOptions, setShareOptions] = useState([])
const [values, setValues] = useState(initialValue || {})

useEffect(() => {
const fetchShareOptions = async () => {
try {
const response = await axios.get('/api/share', {params: { project_name: projectName }})
const result = [
{ label: 'Internal users', value: '__everyone__', 'shareType': 'global' },
{ label: 'Guest users', value: '__guests__', 'shareType': 'global' },
]
for (const option of response.data.options) {
result.push({ label: option.label, value: option.value, shareType: option.shareType })
}

setShareOptions(result)
} catch (error) {
console.error('Error fetching share options:', error)
toast.error('Failed to fetch share options')
}
}

fetchShareOptions()
}, [projectName])


const footer = (
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', flexDirection: 'row' }}>
<Button onClick={() => onSubmit(values)} label="Submit" />
<Button onClick={() => onSubmit(null)} label="Cancel" />
</div>
)

return (
<Dialog
header="Edit Access"
footer={footer}
isOpen
size="lg"
onClose={() => onSubmit(null)}
style={{ width: '600px', height: '600px' }}
>
<ShareOptionsContainer>
{shareOptions.map((option) => (
<ShareOption key={option.value}>
{option.label} ({option.shareType})
<input
type="checkbox"
checked={values[option.value] > 0}
onChange={(e) => {
const newValue = { ...values, [option.value]: e.target.checked ? 10 : undefined }
console.log(newValue)
setValues(newValue)
}}
/>
</ShareOption>
))}
</ShareOptionsContainer>
</Dialog>
)
}




const AccessWidget = (props) => {
const { path } = parseContext(props)
const projectName = props?.formContext?.headerProjectName

const [value, setValue] = useState(props.formData || {})
const [isOpen, setIsOpen] = useState(false)

const onDialogSubmit = (commitValue) => {
console.log("Dialog submitted with value:", commitValue)
if (commitValue === null) {
setIsOpen(false)
return
}

const isChanged = commitValue !== value
setValue(commitValue)
props.onChange(commitValue)
setTimeout(() => {
updateChangedKeys(props, isChanged, path)
setStatus('unchanged')
}, 100)
setIsOpen(false)
}


const dialogComponent = useMemo(() => {
if (!isOpen) return
return (
<AccessEditorDialog
projectName={projectName}
initialValue={value}
onSubmit={onDialogSubmit}
/>
)
}, [value, isOpen, projectName])


return (
<>
<Button
onClick={() => {
setIsOpen(true);
console.log("Opening access editor")
}}
label="Edit Access"
icon="lock"
/>
{dialogComponent}
</>
)
}


/*
const [textValue, setTextValue] = useState('{}')
const [status, setStatus] = useState('unchanged')

useEffect(() => {
setTextValue(JSON.stringify(props.formData || {}, null, 2))
}, [value])


const onCommit = () => {
let commitValue = {}
try {
commitValue = JSON.parse(textValue)
} catch (e) {
toast.error("Invalid JSON")
setStatus('error')
return
}

const isChanged = commitValue !== value
setValue(commitValue)
props.onChange(commitValue)

setTimeout(() => {
updateChangedKeys(props, isChanged, path)
setStatus('unchanged')
}, 100)
}


return (
<>
<CodeEditorWrapper className={status}>
<CodeEditor
wrap="false"
value={textValue}
language="json"
onChange={(e) => {
setTextValue(e.target.value)
setStatus('changed')
}}
onBlur={onCommit}
/>
</CodeEditorWrapper>
</>
)
}
*/
export default AccessWidget


Loading