diff --git a/client/client.ts b/client/client.ts
index ae80a45a..019d5558 100644
--- a/client/client.ts
+++ b/client/client.ts
@@ -88,21 +88,6 @@ export class Client {
return await makeRequest<{ path: string }>('/folder/move', props)
}
- // Package
-
- async packageFetch(props: {
- url: string
- path?: string
- folder?: string
- deduplicate?: boolean
- }) {
- return await makeRequest<{ path: string }>('/package/fetch', props)
- }
-
- async packagePublish(props: { path: string; control: types.IControl }) {
- return await makeRequest<{ url: string }>('/package/publish', props)
- }
-
// Table
async tableCount(props: { path: string; valid?: boolean }) {
diff --git a/client/components/Editors/Package/Layout.tsx b/client/components/Editors/Package/Layout.tsx
deleted file mode 100644
index 438985f7..00000000
--- a/client/components/Editors/Package/Layout.tsx
+++ /dev/null
@@ -1,175 +0,0 @@
-import * as React from 'react'
-import capitalize from 'lodash/capitalize'
-import Box from '@mui/material/Box'
-import Grid from '@mui/material/Grid'
-import MenuTree from '../../Parts/Trees/Menu'
-import EditorHelp from '../Base/Help'
-import SelectField from '../../Parts/Fields/Select'
-import Resource from '../Resource'
-import Dialect from '../Dialect'
-import Schema from '../Schema'
-import PackageSection from './Sections/Package'
-import LicensesSection from './Sections/Licenses'
-import ResourcesSection from './Sections/Resources'
-import SourcesSection from './Sections/Sources'
-import ContributorsSection from './Sections/Contributors'
-import { useStore, selectors, select } from './store'
-import * as types from '../../../types'
-
-export default function Layout() {
- return
-}
-
-// TODO: improve menu implementation (move some state to store / reduce re-renders)
-function LayoutWithMenu() {
- const shallow = useStore((state) => state.shallow)
- const section = useStore((state) => state.section)
- const resource = useStore(selectors.resource)
- const format = useStore(select(selectors.resource, (resource) => resource.format))
- const dialect = useStore(select(selectors.resource, (resource) => resource.dialect))
- const schema = useStore(select(selectors.resource, (resource) => resource.schema))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateState = useStore((state) => state.updateState)
- const updateResource = useStore((state) => state.updateResource)
- const helpItem = useStore((state) => state.helpItem)
-
- const MENU_ITEMS: types.IMenuItem[] = [
- { section: 'package', name: 'Package' },
- { section: 'package/resources', name: 'Resources' },
- { section: 'package/licenses', name: 'Licenses' },
- { section: 'package/contributors', name: 'Contributors' },
- { section: 'package/sources', name: 'Sources' },
- ]
-
- if (!shallow) {
- MENU_ITEMS.push(
- ...[
- { section: 'resource', name: 'Resource' },
- { section: 'resource/integrity', name: 'Integrity' },
- { section: 'resource/licenses', name: 'Licenses' },
- { section: 'resource/contributors', name: 'Contributors' },
- { section: 'resource/sources', name: 'Sources' },
- { section: 'dialect', name: 'Dialect', disabled: resource.type !== 'table' },
- { section: 'dialect/format', name: capitalize(format) || 'Format' },
- { section: 'schema', name: 'Schema', disabled: resource.type !== 'table' },
- { section: 'schema/fields', name: 'Fields' },
- { section: 'schema/foreignKeys', name: 'Foreign Keys' },
- ]
- )
- }
-
- // We use memo to avoid nested editors re-rerender
- const handleResourceChange = React.useMemo(() => {
- return (resource: types.IResource) => updateResource(resource)
- }, [])
- const handleDialectChange = React.useMemo(() => {
- return (dialect: types.IDialect) => updateResource({ dialect })
- }, [])
- const handleSchemaChange = React.useMemo(() => {
- return (schema: types.ISchema) => updateResource({ schema })
- }, [])
-
- // We use memo to avoid nested editors re-rerender
- const externalMenu = React.useMemo(() => {
- return { section }
- }, [])
- React.useEffect(() => {
- const isTabular = section.startsWith('dialect') || section.startsWith('schema')
- if (resource.type !== 'table' && isTabular) {
- updateHelp('resource')
- updateState({ section: 'resource' })
- externalMenu.section = 'resource'
- }
- }, [resource])
-
- return (
-
-
- {!shallow && (
-
-
-
- )}
- {
- updateHelp(section)
- updateState({ section })
- externalMenu.section = section
- }}
- />
-
-
-
- {!shallow && (
-
-
-
-
- {resource.type === 'table' && (
-
-
-
-
-
-
-
-
- )}
-
- )}
-
-
-
-
-
- )
-}
-
-function Sections() {
- const section = useStore((state) => state.section)
- if (!section) return null
- if (section == 'package') return
- if (section == 'package/resources') return
- if (section == 'package/licenses') return
- if (section == 'package/contributors') return
- if (section == 'package/sources') return
- return null
-}
-
-export function ResourceSelector() {
- const resource = useStore(selectors.resource)
- const updateResourceState = useStore((state) => state.updateResourceState)
- const resourceNames = useStore(selectors.resourceNames)
- if (!resource) return null
- return (
- updateResourceState({ index: resourceNames.indexOf(value) })}
- />
- )
-}
diff --git a/client/components/Editors/Package/Sections/Contributors.tsx b/client/components/Editors/Package/Sections/Contributors.tsx
deleted file mode 100644
index ccebec2c..00000000
--- a/client/components/Editors/Package/Sections/Contributors.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-import * as React from 'react'
-import Box from '@mui/material/Box'
-import Columns from '../../../Parts/Grids/Columns'
-import InputField from '../../../Parts/Fields/Input'
-import EditorItem from '../../Base/Item'
-import EditorList from '../../Base/List'
-import EditorListItem from '../../Base/ListItem'
-import EditorSearch from '../../Base/Search'
-import { useStore, selectors, select } from '../store'
-import validator from 'validator'
-
-export default function Contributors() {
- const index = useStore((state) => state.contributorState.index)
- return index === undefined ? :
-}
-
-function ContributorList() {
- const query = useStore((state) => state.contributorState.query)
- const contributorItems = useStore(selectors.contributorItems)
- const updateContributorState = useStore((state) => state.updateContributorState)
- const addContributor = useStore((state) => state.addContributor)
- const removeContributor = useStore((state) => state.removeContributor)
- return (
- addContributor()}
- SearchInput={
- updateContributorState({ query })}
- />
- }
- >
- {contributorItems.map(({ index, contributor }) => (
- {
- updateContributorState({ index })
- }}
- onRemoveClick={() => removeContributor(index)}
- />
- ))}
-
- )
-}
-
-function ContributorItem() {
- const title = useStore(
- select(selectors.contributor, (contributor) => contributor.title)
- )
- const isExtras = useStore((state) => state.contributorState.isExtras)
- const updateContributorState = useStore((state) => state.updateContributorState)
- return (
- updateContributorState({ isExtras: !isExtras })}
- onBackClick={() => updateContributorState({ index: undefined, isExtras: false })}
- >
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-function Title() {
- const title = useStore(
- select(selectors.contributor, (contributor) => contributor.title)
- )
- const updateHelp = useStore((state) => state.updateHelp)
- const updateContributor = useStore((state) => state.updateContributor)
- return (
- updateHelp('package/contributors/title')}
- onChange={(title) => updateContributor({ title })}
- />
- )
-}
-
-function Email() {
- const email = useStore(
- select(selectors.contributor, (contributor) => contributor.email)
- )
- const updateHelp = useStore((state) => state.updateHelp)
- const updateContributor = useStore((state) => state.updateContributor)
- const [isValid, setIsValid] = React.useState(isValidEmail())
- function isValidEmail() {
- return email ? validator.isEmail(email) : true
- }
- return (
- updateHelp('package/contributors/email')}
- onBlur={() => {
- setIsValid(isValidEmail())
- }}
- onChange={(value) => updateContributor({ email: value })}
- helperText={!isValid ? 'Email is not valid.' : ''}
- />
- )
-}
-
-function Path() {
- const path = useStore(select(selectors.contributor, (contributor) => contributor.path))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateContributor = useStore((state) => state.updateContributor)
- return (
- updateHelp('package/contributors/path')}
- onChange={(path) => updateContributor({ path })}
- />
- )
-}
-
-function Role() {
- const role = useStore(select(selectors.contributor, (contributor) => contributor.role))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateContributor = useStore((state) => state.updateContributor)
- return (
- updateHelp('package/contributors/role')}
- onChange={(role) => updateContributor({ role })}
- />
- )
-}
diff --git a/client/components/Editors/Package/Sections/Licenses.tsx b/client/components/Editors/Package/Sections/Licenses.tsx
deleted file mode 100644
index 0b42323c..00000000
--- a/client/components/Editors/Package/Sections/Licenses.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import * as React from 'react'
-import Box from '@mui/material/Box'
-import Columns from '../../../Parts/Grids/Columns'
-import InputField from '../../../Parts/Fields/Input'
-import EditorItem from '../../Base/Item'
-import EditorList from '../../Base/List'
-import EditorListItem from '../../Base/ListItem'
-import EditorSearch from '../../Base/Search'
-import { useStore, selectors, select } from '../store'
-import validator from 'validator'
-
-export default function Licenses() {
- const index = useStore((state) => state.licenseState.index)
- return index === undefined ? :
-}
-
-function LicenseList() {
- const query = useStore((state) => state.licenseState.query)
- const licenseItems = useStore(selectors.licenseItems)
- const updateLicenseState = useStore((state) => state.updateLicenseState)
- const addLicense = useStore((state) => state.addLicense)
- const removeLicense = useStore((state) => state.removeLicense)
- return (
- addLicense()}
- SearchInput={
- updateLicenseState({ query })}
- />
- }
- >
- {licenseItems.map(({ index, license }) => (
- updateLicenseState({ index })}
- onRemoveClick={() => removeLicense(index)}
- />
- ))}
-
- )
-}
-
-function LicenseItem() {
- const name = useStore(select(selectors.license, (license) => license.name))
- const isExtras = useStore((state) => state.licenseState.isExtras)
- const updateLicenseState = useStore((state) => state.updateLicenseState)
- return (
- updateLicenseState({ isExtras: !isExtras })}
- onBackClick={() => updateLicenseState({ index: undefined, isExtras: false })}
- >
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-function Name() {
- const name = useStore(select(selectors.license, (license) => license.name))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateLicense = useStore((state) => state.updateLicense)
- return (
- updateHelp('package/licenses/name')}
- onChange={(name) => updateLicense({ name })}
- />
- )
-}
-
-function Title() {
- const title = useStore(select(selectors.license, (license) => license.title))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateLicense = useStore((state) => state.updateLicense)
- const [isValid, setIsValid] = React.useState(isValidTitle())
- function isValidTitle() {
- return title ? !validator.isNumeric(title) : true
- }
- return (
- updateHelp('package/licenses/title')}
- onBlur={() => {
- setIsValid(isValidTitle())
- }}
- onChange={(value) => updateLicense({ title: value || undefined })}
- helperText={!isValid ? 'Title is not valid.' : ''}
- />
- )
-}
-
-function Path() {
- const path = useStore(select(selectors.license, (license) => license.path))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateLicense = useStore((state) => state.updateLicense)
- return (
- updateHelp('package/licenses/path')}
- onChange={(path) => updateLicense({ path })}
- />
- )
-}
diff --git a/client/components/Editors/Package/Sections/Package.tsx b/client/components/Editors/Package/Sections/Package.tsx
deleted file mode 100644
index 0c8e8b6c..00000000
--- a/client/components/Editors/Package/Sections/Package.tsx
+++ /dev/null
@@ -1,165 +0,0 @@
-import * as React from 'react'
-import Grid from '@mui/material/Grid'
-import InputField from '../../../Parts/Fields/Input'
-import DateTimePickerField from '../../../Parts/Fields/DateTimePicker'
-import MultilineField from '../../../Parts/Fields/Multiline'
-import EditorSection from '../../Base/Section'
-import { useStore } from '../store'
-import validator from 'validator'
-import dayjs from 'dayjs'
-
-export default function Package() {
- const updateHelp = useStore((state) => state.updateHelp)
- return (
- updateHelp('package')}>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-function Name() {
- const name = useStore((state) => state.descriptor.name)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- const [isValid, setIsValid] = React.useState(isValidName())
- function isValidName() {
- return name ? validator.isSlug(name) : true
- }
- return (
- updateHelp('package/name')}
- onBlur={() => {
- setIsValid(isValidName())
- }}
- onChange={(value) => updateDescriptor({ name: value || undefined })}
- helperText={!isValid ? 'Name is not valid.' : ''}
- />
- )
-}
-
-function Title() {
- const title = useStore((state) => state.descriptor.title)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- const [isValid, setIsValid] = React.useState(isValidTitle())
- function isValidTitle() {
- return title ? !validator.isNumeric(title) : true
- }
- return (
- updateHelp('package/title')}
- onBlur={() => {
- setIsValid(isValidTitle())
- }}
- onChange={(value) => updateDescriptor({ title: value || undefined })}
- helperText={!isValid ? 'Title is not valid.' : ''}
- />
- )
-}
-
-function Description() {
- const description = useStore((state) => state.descriptor.description)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- return (
- updateHelp('package/description')}
- onChange={(value) => updateDescriptor({ description: value || undefined })}
- />
- )
-}
-
-function Homepage() {
- const homepage = useStore((state) => state.descriptor.homepage)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- return (
- updateHelp('package/homepage')}
- onChange={(value) => updateDescriptor({ homepage: value || undefined })}
- />
- )
-}
-
-function Version() {
- const version = useStore((state) => state.descriptor.version)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- return (
- updateHelp('package/version')}
- onChange={(value) => updateDescriptor({ version: value || undefined })}
- />
- )
-}
-function Created() {
- const created = useStore((state) => state.descriptor.created)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- const updateHelp = useStore((state) => state.updateHelp)
- return (
- updateHelp('package/created')}
- onChange={(value) => {
- updateDescriptor({ created: value?.format('YYYY-MM-DDTHH:mm:ss') })
- }}
- errorMessage={'Date is not valid'}
- />
- )
-}
-
-function Keywords() {
- const keywords = useStore((state) => state.descriptor.keywords)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- return (
- updateHelp('package/keywords')}
- onChange={(value) =>
- updateDescriptor({ keywords: value ? value.split(',') : undefined })
- }
- />
- )
-}
-
-function Image() {
- const image = useStore((state) => state.descriptor.image)
- const updateHelp = useStore((state) => state.updateHelp)
- const updateDescriptor = useStore((state) => state.updateDescriptor)
- return (
- updateHelp('package/image')}
- onChange={(value) => updateDescriptor({ image: value || undefined })}
- />
- )
-}
diff --git a/client/components/Editors/Package/Sections/Resources.tsx b/client/components/Editors/Package/Sections/Resources.tsx
deleted file mode 100644
index b4c27aae..00000000
--- a/client/components/Editors/Package/Sections/Resources.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import EditorList from '../../Base/List'
-import EditorListItem from '../../Base/ListItem'
-import EditorSearch from '../../Base/Search'
-import { useStore, selectors } from '../store'
-
-export default function Resources() {
- const query = useStore((state) => state.resourceState.query)
- const resourceItems = useStore(selectors.resourceItems)
- const updateResourceState = useStore((state) => state.updateResourceState)
- const addResource = useStore((state) => state.addResource)
- const removeResource = useStore((state) => state.removeResource)
- const onResourceSelected = useStore((state) => state.onResourceSelected)
- return (
- addResource()}
- SearchInput={
- updateResourceState({ query })}
- />
- }
- >
- {resourceItems.map(({ index, resource }) => (
- {
- updateResourceState({ index })
- if (onResourceSelected) onResourceSelected(resource.name)
- }}
- onRemoveClick={() => removeResource(index)}
- />
- ))}
-
- )
-}
diff --git a/client/components/Editors/Package/Sections/Sources.tsx b/client/components/Editors/Package/Sections/Sources.tsx
deleted file mode 100644
index 7aaa2d2c..00000000
--- a/client/components/Editors/Package/Sections/Sources.tsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import * as React from 'react'
-import Box from '@mui/material/Box'
-import Columns from '../../../Parts/Grids/Columns'
-import InputField from '../../../Parts/Fields/Input'
-import EditorItem from '../../Base/Item'
-import EditorList from '../../Base/List'
-import EditorListItem from '../../Base/ListItem'
-import EditorSearch from '../../Base/Search'
-import { useStore, selectors, select } from '../store'
-import validator from 'validator'
-
-export default function Sources() {
- const index = useStore((state) => state.sourceState.index)
- return index === undefined ? :
-}
-
-function SourceList() {
- const query = useStore((state) => state.sourceState.query)
- const sourceItems = useStore(selectors.sourceItems)
- const updateSourceState = useStore((state) => state.updateSourceState)
- const addSource = useStore((state) => state.addSource)
- const removeSource = useStore((state) => state.removeSource)
- return (
- addSource()}
- SearchInput={
- updateSourceState({ query })}
- />
- }
- >
- {sourceItems.map(({ index, source }) => (
- {
- updateSourceState({ index })
- }}
- onRemoveClick={() => removeSource(index)}
- />
- ))}
-
- )
-}
-
-function SourceItem() {
- const title = useStore(select(selectors.source, (source) => source.title))
- const isExtras = useStore((state) => state.sourceState.isExtras)
- const updateSourceState = useStore((state) => state.updateSourceState)
- return (
- updateSourceState({ isExtras: !isExtras })}
- onBackClick={() => updateSourceState({ index: undefined, isExtras: false })}
- >
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-function Title() {
- const title = useStore(select(selectors.source, (source) => source.title))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateSource = useStore((state) => state.updateSource)
- return (
- updateHelp('package/sources/title')}
- onChange={(title) => updateSource({ title })}
- />
- )
-}
-
-function Path() {
- const path = useStore(select(selectors.source, (source) => source.path))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateSource = useStore((state) => state.updateSource)
- return (
- updateHelp('package/sources/path')}
- onChange={(path) => updateSource({ path })}
- />
- )
-}
-
-function Email() {
- const email = useStore(select(selectors.source, (source) => source.email))
- const updateHelp = useStore((state) => state.updateHelp)
- const updateSource = useStore((state) => state.updateSource)
- const [isValid, setIsValid] = React.useState(isValidEmail())
- function isValidEmail() {
- return email ? validator.isEmail(email) : true
- }
- return (
- updateHelp('package/sources/email')}
- onBlur={() => {
- setIsValid(isValidEmail())
- }}
- onChange={(value) => updateSource({ email: value || undefined })}
- helperText={!isValid ? 'Email is not valid.' : ''}
- />
- )
-}
diff --git a/client/components/Editors/Package/help.yaml b/client/components/Editors/Package/help.yaml
deleted file mode 100644
index f4815931..00000000
--- a/client/components/Editors/Package/help.yaml
+++ /dev/null
@@ -1,124 +0,0 @@
-# Package
-
-package:
- - Package
- - https://specs.frictionlessdata.io/data-package/
- - A simple container format for describing a coherent collection of data in a single package. It provides the basis for convenient delivery, installation and management of datasets.
-
-package/name:
- - Name
- - https://specs.frictionlessdata.io/data-package/#name
- - Slugified the name of the package.
-
-package/title:
- - Title
- - https://specs.frictionlessdata.io/data-package/#title
- - A human-readable title.
-
-package/description:
- - Description
- - https://specs.frictionlessdata.io/data-package/#description
- - A description of the package. The description MUST be markdown formatted – this also allows for simple plain text as plain text is itself valid markdown.
-
-package/homepage:
- - Homepage
- - https://specs.frictionlessdata.io/data-package/#homepage
- - A URL for the home on the web that is related to this data package.
-
-package/keywords:
- - Keywords
- - https://specs.frictionlessdata.io/data-package/#keywords
- - An Array of string keywords to assist users searching for the package in catalogs.
-
-package/version:
- - Version
- - https://specs.frictionlessdata.io/data-package/#version
- - A version string identifying the version of the package.
-
-package/created:
- - Created
- - https://specs.frictionlessdata.io/data-package/#created
- - The datetime on which this was created.
-
-package/image:
- - Image
- - https://specs.frictionlessdata.io/data-package/#image
- - An image path to use for this data package.
-
-# Resources
-
-package/resources:
- - Resources
- - https://specs.frictionlessdata.io/data-package/#resource-information
- - Packaged data resources are described in the resources property of the package descriptor.
-
-# Licenses
-
-package/licenses:
- - Licenses
- - https://specs.frictionlessdata.io/data-package/#licenses
- - The license(s) under which the resource is provided.
-
-package/licenses/name:
- - Name
- - https://specs.frictionlessdata.io/data-package/#licenses
- - The name MUST be an Open Definition license ID e.g. ODC-BY-1.0
-
-package/licenses/path:
- - Path
- - https://specs.frictionlessdata.io/data-package/#licenses
- - A url-or-path string, that is a fully qualified HTTP address, or a relative POSIX path for this license.
-
-package/licenses/title:
- - Title
- - https://specs.frictionlessdata.io/data-package/#licenses
- - A human-readable title or label for this license e.g. "Open Data Commons Public Domain Dedication and License v1.0".
-
-# Contributors
-
-package/contributors:
- - Contributors
- - https://specs.frictionlessdata.io/data-package/#contributors
- - A name/title of the contributor (name for person, name/title of organization).
-
-package/contributors/title:
- - Title
- - https://specs.frictionlessdata.io/data-package/#contributors
- - Title of the source (e.g. document or organization name).
-
-package/contributors/email:
- - Email
- - https://specs.frictionlessdata.io/data-package/#contributors
- - An email address.
-
-package/contributors/path:
- - Path
- - https://specs.frictionlessdata.io/data-package/#contributors
- - A fully qualified http URL pointing to a relevant location online for the contributor.
-
-package/contributors/role:
- - Role
- - https://specs.frictionlessdata.io/data-package/#contributors
- - A string describing the role of the contributor.
-
-# Sources
-
-package/sources:
- - Sources
- - https://specs.frictionlessdata.io/data-package/#sources
- - Raw sources for the data package.
-
-package/sources/title:
- - Title
- - https://specs.frictionlessdata.io/data-package/#sources
- - Title of the source (e.g. document or organization name).
-
-package/sources/path:
- - Path
- - https://specs.frictionlessdata.io/data-package/#sources
- - A url-or-path string, that is a fully qualified HTTP address, or a relative POSIX path.
-
-package/sources/email:
- - Email
- - https://specs.frictionlessdata.io/data-package/#sources
- - An email address.
diff --git a/client/components/Editors/Package/index.tsx b/client/components/Editors/Package/index.tsx
deleted file mode 100644
index 392af6b8..00000000
--- a/client/components/Editors/Package/index.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import * as React from 'react'
-import { StoreProvider, makeStore } from './store'
-import * as types from '../../../types'
-import Layout from './Layout'
-
-export interface PackageProps {
- package?: types.IPackage
- shallow?: boolean
- onChange?: (pkg: types.IPackage) => void
- onAddResource?: () => void
- onResourceSelected?: (name?: string) => void
-}
-
-export default function Package(props: PackageProps) {
- const store = React.useMemo(() => makeStore(props), Object.values(props))
- return (
-
-
-
- )
-}
diff --git a/client/components/Editors/Package/store.ts b/client/components/Editors/Package/store.ts
deleted file mode 100644
index bb9253ae..00000000
--- a/client/components/Editors/Package/store.ts
+++ /dev/null
@@ -1,304 +0,0 @@
-import * as React from 'react'
-import * as zustand from 'zustand'
-import { assert } from 'ts-essentials'
-import noop from 'lodash/noop'
-import cloneDeep from 'lodash/cloneDeep'
-import { createStore } from 'zustand/vanilla'
-import { createSelector } from 'reselect'
-import { PackageProps } from './index'
-import * as settings from '../../../settings'
-import * as helpers from '../../../helpers'
-import * as types from '../../../types'
-import help from './help.yaml'
-
-const DEFAULT_HELP_ITEM = helpers.readHelpItem(help, 'package')!
-
-interface ISectionState {
- query?: string
- index?: number
- isExtras?: boolean
-}
-
-interface State {
- descriptor: types.IPackage
- shallow?: boolean
- onChange: (pkg: types.IPackage) => void
- onAddResource?: () => void
- onResourceSelected?: (name: string) => void
- section: string
- helpItem: types.IHelpItem
- updateState: (patch: Partial) => void
- updateHelp: (path: string) => void
- updateDescriptor: (patch: Partial) => void
-
- // Resources
-
- resourceState: ISectionState & { index: number }
- updateResourceState: (patch: Partial) => void
- updateResource: (patch: Partial) => void
- removeResource: (index: number) => void
- addResource: () => void
-
- // Licenses
-
- licenseState: ISectionState
- updateLicenseState: (patch: Partial) => void
- updateLicense: (patch: Partial) => void
- removeLicense: (index: number) => void
- addLicense: () => void
-
- // Sources
-
- sourceState: ISectionState
- updateSourceState: (patch: Partial) => void
- updateSource: (patch: Partial) => void
- removeSource: (index: number) => void
- addSource: () => void
-
- // Contributors
-
- contributorState: ISectionState
- updateContributorState: (patch: Partial) => void
- updateContributor: (patch: Partial) => void
- removeContributor: (index: number) => void
- addContributor: () => void
-}
-
-export function makeStore(props: PackageProps) {
- return createStore((set, get) => ({
- descriptor: props.package || cloneDeep(settings.INITIAL_PACKAGE),
- shallow: props.shallow,
- onChange: props.onChange || noop,
- onAddResource: props.onAddResource,
- onResourceSelected: props.onResourceSelected,
- section: 'package',
- helpItem: DEFAULT_HELP_ITEM,
- updateState: (patch) => {
- set({ ...patch })
- },
- updateHelp: (path) => {
- const helpItem = helpers.readHelpItem(help, path) || DEFAULT_HELP_ITEM
- set({ helpItem })
- },
- updateDescriptor: (patch) => {
- const { descriptor, onChange } = get()
- Object.assign(descriptor, patch)
- onChange(descriptor)
- set({ descriptor })
- },
-
- // Resources
-
- resourceState: { index: 0 },
- updateResourceState: (patch) => {
- const { resourceState } = get()
- set({ resourceState: { ...resourceState, ...patch } })
- },
- updateResource: (patch) => {
- const { descriptor, updateDescriptor } = get()
- const resource = selectors.resource(get())!
- const resources = descriptor.resources!
- Object.assign(resource, patch)
- updateDescriptor({ resources })
- },
- removeResource: (index) => {
- const { descriptor, updateDescriptor, updateResourceState } = get()
- const resources = [...(descriptor.resources || [])]
- resources.splice(index, 1)
- updateResourceState({ index: undefined, isExtras: false })
- updateDescriptor({ resources })
- },
- // TODO: scroll to newly created resource
- addResource: () => {
- const { descriptor, updateDescriptor, onAddResource } = get()
- if (onAddResource) return onAddResource()
- const resources = [...(descriptor.resources || [])]
- const name = helpers.generateTitle(resources, 'resource')
- resources.push({
- name,
- type: 'table',
- path: 'table.csv',
- })
- updateDescriptor({ resources })
- },
-
- // Licenses
-
- licenseState: {},
- updateLicenseState: (patch) => {
- const { licenseState } = get()
- set({ licenseState: { ...licenseState, ...patch } })
- },
- updateLicense: (patch) => {
- const { descriptor, updateDescriptor, licenseState } = get()
- const index = licenseState.index!
- const license = selectors.license(get())
- const licenses = descriptor.licenses!
- licenses[index] = { ...license, ...patch }
- updateDescriptor({ licenses })
- },
- removeLicense: (index) => {
- const { descriptor, updateDescriptor, updateLicenseState } = get()
- const licenses = [...(descriptor.licenses || [])]
- licenses.splice(index, 1)
- updateLicenseState({ index: undefined, isExtras: false })
- updateDescriptor({ licenses })
- },
- // TODO: scroll to newly created license
- addLicense: () => {
- const { descriptor, updateDescriptor } = get()
- const licenses = [...(descriptor.licenses || [])]
- licenses.push({ name: 'MIT' })
- updateDescriptor({ licenses })
- },
-
- // Sources
-
- sourceState: {},
- updateSourceState: (patch) => {
- const { sourceState } = get()
- set({ sourceState: { ...sourceState, ...patch } })
- },
- updateSource: (patch) => {
- const { descriptor, sourceState, updateDescriptor } = get()
- const index = sourceState.index!
- const source = selectors.source(get())
- const sources = descriptor.sources!
- sources[index] = { ...source, ...patch }
- updateDescriptor({ sources })
- },
- removeSource: (index) => {
- const { descriptor, updateDescriptor, updateSourceState } = get()
- const sources = [...(descriptor.sources || [])]
- sources.splice(index, 1)
- updateSourceState({ index: undefined, isExtras: false })
- updateDescriptor({ sources })
- },
- // TODO: scroll to newly created source
- addSource: () => {
- const { descriptor, updateDescriptor } = get()
- const sources = [...(descriptor.sources || [])]
- sources.push({ title: helpers.generateTitle(sources, 'source') })
- updateDescriptor({ sources })
- },
-
- // Contributors
-
- contributorState: {},
- updateContributorState: (patch) => {
- const { contributorState } = get()
- set({ contributorState: { ...contributorState, ...patch } })
- },
- updateContributor: (patch) => {
- const { descriptor, contributorState, updateDescriptor } = get()
- const index = contributorState.index!
- const contributor = selectors.contributor(get())
- const contributors = descriptor.contributors!
- contributors[index] = { ...contributor, ...patch }
- updateDescriptor({ contributors })
- },
- removeContributor: (index) => {
- const { descriptor, updateDescriptor, updateContributorState } = get()
- const contributors = [...(descriptor.contributors || [])]
- contributors.splice(index, 1)
- updateContributorState({ index: undefined, isExtras: false })
- updateDescriptor({ contributors })
- },
- // TODO: scroll to newly created contributor
- addContributor: () => {
- const { descriptor, updateDescriptor } = get()
- const contributors = [...(descriptor.contributors || [])]
- contributors.push({ title: helpers.generateTitle(contributors, 'contributor') })
- updateDescriptor({ contributors })
- },
- }))
-}
-
-export const select = createSelector
-export const selectors = {
- // Resources
-
- resource: (state: State) => {
- const index = state.resourceState.index
- const resources = state.descriptor.resources || []
- const resource = resources[index] ?? {}
- return resource
- },
- resourceItems: (state: State) => {
- const items = []
- const query = state.resourceState.query
- for (const [index, resource] of (state.descriptor.resources || []).entries()) {
- if (query && !resource.name.toLowerCase().includes(query.toLowerCase())) continue
- items.push({ index, resource })
- }
- return items
- },
- resourceNames: (state: State) => {
- return state.descriptor.resources.map((resource) => resource.name)
- },
-
- // Licenses
-
- license: (state: State) => {
- const index = state.licenseState.index!
- const licenses = state.descriptor.licenses || []
- const license = licenses[index] ?? {}
- return license
- },
- licenseItems: (state: State) => {
- const items = []
- const query = state.licenseState.query
- for (const [index, license] of (state.descriptor.licenses || []).entries()) {
- if (query && !license.name.toLowerCase().includes(query.toLowerCase())) continue
- items.push({ index, license })
- }
- return items
- },
-
- // Sources
-
- source: (state: State) => {
- const index = state.sourceState.index!
- const sources = state.descriptor.sources || []
- const source = sources[index] ?? {}
- return source
- },
- sourceItems: (state: State) => {
- const items = []
- const query = state.sourceState.query
- for (const [index, source] of (state.descriptor.sources || []).entries()) {
- if (query && !source.title.toLowerCase().includes(query.toLowerCase())) continue
- items.push({ index, source })
- }
- return items
- },
-
- // Contributors
-
- contributor: (state: State) => {
- const index = state.contributorState.index!
- const contributors = state.descriptor.contributors || []
- const contributor = contributors[index] ?? {}
- return contributor
- },
- contributorItems: (state: State) => {
- const items = []
- const query = state.contributorState.query
- for (const [index, contributor] of (state.descriptor.contributors || []).entries()) {
- if (query && !contributor.title.toLowerCase().includes(query.toLowerCase())) {
- continue
- }
- items.push({ index, contributor })
- }
- return items
- },
-}
-
-export function useStore(selector: (state: State) => R): R {
- const store = React.useContext(StoreContext)
- assert(store, 'store provider is required')
- return zustand.useStore(store, selector)
-}
-
-const StoreContext = React.createContext | null>(null)
-export const StoreProvider = StoreContext.Provider
diff --git a/client/components/Parts/Trees/File.tsx b/client/components/Parts/Trees/File.tsx
index 0667c9c8..647c5c75 100644
--- a/client/components/Parts/Trees/File.tsx
+++ b/client/components/Parts/Trees/File.tsx
@@ -278,8 +278,6 @@ function TreeItemIcon(props: { nodeId: string; item: types.IFileTreeItem }) {
: theme.palette.OKFNGreenBlue.main
const fontWeight = 'normal'
- // When data package is enabled consider highlighting it
- // const fontWeight = props.item.type === 'package' ? 'bold' : 'normal'
return (
= { type: 'ckan' }
-export const INITIAL_PACKAGE: types.IPackage = { resources: [] }
export const INITIAL_PORTAL: types.IPortal = { type: 'ckan' }
export const INITIAL_HISTORY: types.IHistory = { changes: [] }
export const INITIAL_RESOURCE: types.IResource = {
@@ -134,7 +130,6 @@ export const TYPE_ICONS: { [key: string]: React.ElementType } = {
folder: FolderIcon,
image: ImageIcon,
map: MapIcon,
- package: [SourceIcon, WidgetsIcon][0],
pipeline: AccountTree,
resource: DescriptionIcon,
schema: DescriptionIcon,
diff --git a/client/types/index.ts b/client/types/index.ts
index 253eea42..04cb0d55 100644
--- a/client/types/index.ts
+++ b/client/types/index.ts
@@ -9,7 +9,6 @@ export * from './help'
export * from './history'
export * from './license'
export * from './menu'
-export * from './package'
export * from './portal'
export * from './progress'
export * from './record'
diff --git a/client/types/package.ts b/client/types/package.ts
deleted file mode 100644
index 7c5a9dba..00000000
--- a/client/types/package.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { IResource } from './resource'
-import { IContributor } from './contributor'
-import { ILicense } from './license'
-import { ISource } from './source'
-
-export interface IPackage {
- name?: string
- title?: string
- description?: string
- licenses?: ILicense[]
- homepage?: string
- version?: string
- created?: string
- image?: string
- resources: IResource[]
- contributors?: IContributor[]
- keywords?: string[]
- sources?: ISource[]
-}
diff --git a/server/helpers/resource.py b/server/helpers/resource.py
index ae01d22f..a993845c 100644
--- a/server/helpers/resource.py
+++ b/server/helpers/resource.py
@@ -3,7 +3,7 @@
from typing import TYPE_CHECKING
from frictionless import FrictionlessException, Indexer, Report
-from frictionless.resources import PackageResource, ResourceResource, TableResource
+from frictionless.resources import ResourceResource, TableResource
if TYPE_CHECKING:
from frictionless import Resource
@@ -27,7 +27,7 @@ def index_resource(project: Project, resource: Resource, table_name: str):
report = indexer.index()
# Container resource
- if isinstance(resource, (ResourceResource, PackageResource)):
+ if isinstance(resource, (ResourceResource)):
try:
errors = []
resource.read_metadata()