mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 11:52:59 +03:00
fixes
This commit is contained in:
parent
627ee76e48
commit
04c66eca34
@ -308,7 +308,6 @@ export default [
|
||||
],
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
'no-restricted-syntax': ['error', ...RESTRICTED_SYNTAXES],
|
||||
'prefer-arrow-callback': 'error',
|
||||
'prefer-const': 'error',
|
||||
// Not relevant because TypeScript checks types.
|
||||
'react/prop-types': 'off',
|
||||
|
@ -28,7 +28,8 @@
|
||||
"opener": "^1.5.2",
|
||||
"string-length": "^5.0.1",
|
||||
"tar": "^6.1.13",
|
||||
"yargs": "17.6.2"
|
||||
"yargs": "17.6.2",
|
||||
"mkcert": "3.2.0"
|
||||
},
|
||||
"comments": {
|
||||
"electron-builder": "Cannot be updated to a newer version because of a NSIS installer issue: https://github.com/enso-org/enso/issues/5169"
|
||||
|
@ -6,6 +6,7 @@ import * as http from 'node:http'
|
||||
import * as os from 'node:os'
|
||||
import * as path from 'node:path'
|
||||
import * as stream from 'node:stream'
|
||||
import * as mkcert from 'mkcert'
|
||||
|
||||
import * as mime from 'mime-types'
|
||||
import * as portfinder from 'portfinder'
|
||||
@ -107,10 +108,28 @@ export class Server {
|
||||
|
||||
/** Start the server. */
|
||||
run(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const defaultValidity = 365
|
||||
const ca = await mkcert.createCA({
|
||||
organization: 'Hello CA',
|
||||
countryCode: 'NP',
|
||||
state: 'Bagmati',
|
||||
locality: 'Kathmandu',
|
||||
validity: defaultValidity,
|
||||
})
|
||||
const cert = await mkcert.createCert({
|
||||
ca: { key: ca.key, cert: ca.cert },
|
||||
domains: ['127.0.0.1', 'localhost'],
|
||||
validity: defaultValidity,
|
||||
})
|
||||
|
||||
createServer(
|
||||
{
|
||||
http: this.config.port,
|
||||
https: {
|
||||
key: cert.key,
|
||||
cert: cert.cert,
|
||||
port: this.config.port,
|
||||
},
|
||||
handler: this.process.bind(this),
|
||||
},
|
||||
(err, { http: httpServer }) => {
|
||||
|
@ -66,6 +66,18 @@ class App {
|
||||
this.setProjectToOpenOnStartup(id)
|
||||
})
|
||||
|
||||
electron.app.commandLine.appendSwitch('allow-insecure-localhost', 'true')
|
||||
electron.app.commandLine.appendSwitch('ignore-certificate-errors', 'true')
|
||||
electron.app.on(
|
||||
'certificate-error',
|
||||
(event, webContents, url, error, certificate, callback) => {
|
||||
// Prevent having error
|
||||
event.preventDefault()
|
||||
// and continue
|
||||
callback(true)
|
||||
}
|
||||
)
|
||||
|
||||
const { windowSize, chromeOptions, fileToOpen, urlToOpen } = this.processArguments()
|
||||
this.handleItemOpening(fileToOpen, urlToOpen)
|
||||
if (this.args.options.version.value) {
|
||||
@ -439,7 +451,7 @@ class App {
|
||||
searchParams[option.qualifiedName()] = option.value.toString()
|
||||
}
|
||||
}
|
||||
const address = new URL('http://localhost')
|
||||
const address = new URL('https://localhost')
|
||||
address.port = this.serverPort().toString()
|
||||
address.search = new URLSearchParams(searchParams).toString()
|
||||
logger.log(`Loading the window address '${address.toString()}'.`)
|
||||
|
@ -3,6 +3,7 @@
|
||||
import * as childProcess from 'node:child_process'
|
||||
import * as fs from 'node:fs/promises'
|
||||
import * as path from 'node:path'
|
||||
import * as mkcert from 'mkcert'
|
||||
|
||||
import * as esbuild from 'esbuild'
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import * as aria from '#/components/aria'
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export interface LinkProps extends aria.LinkProps {}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function Link(props: LinkProps) {
|
||||
return <aria.Link />
|
||||
}
|
@ -15,7 +15,28 @@ import SvgMask from '#/components/SvgMask'
|
||||
// ==============
|
||||
|
||||
/** Props for a {@link Button}. */
|
||||
export interface ButtonProps extends Readonly<aria.ButtonProps> {
|
||||
export type ButtonProps =
|
||||
| (aria.ButtonProps & BaseButtonProps & PropsWithoutHref)
|
||||
| (aria.LinkProps & BaseButtonProps & PropsWithHref)
|
||||
|
||||
/**
|
||||
* Props for a button with an href.
|
||||
*/
|
||||
interface PropsWithHref {
|
||||
readonly href: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Props for a button without an href.
|
||||
*/
|
||||
interface PropsWithoutHref {
|
||||
readonly href?: never
|
||||
}
|
||||
|
||||
/**
|
||||
* Base props for a button.
|
||||
*/
|
||||
export interface BaseButtonProps {
|
||||
readonly loading?: boolean
|
||||
/**
|
||||
* The variant of the button
|
||||
@ -58,10 +79,18 @@ export type IconPosition = 'end' | 'start'
|
||||
/**
|
||||
* The variant of the button
|
||||
*/
|
||||
export type Variant = 'cancel' | 'custom' | 'delete' | 'icon' | 'outline' | 'primary' | 'submit'
|
||||
export type Variant =
|
||||
| 'cancel'
|
||||
| 'custom'
|
||||
| 'delete'
|
||||
| 'icon'
|
||||
| 'link'
|
||||
| 'outline'
|
||||
| 'primary'
|
||||
| 'submit'
|
||||
|
||||
const DEFAULT_CLASSES =
|
||||
'flex whitespace-nowrap cursor-pointer border border-transparent transition-[opacity,outline-offset] duration-200 ease-in-out select-none text-center items-center justify-center'
|
||||
'flex whitespace-nowrap cursor-pointer border border-transparent transition-[opacity,outline-offset] duration-150 ease-in-out select-none text-center items-center justify-center'
|
||||
const FOCUS_CLASSES =
|
||||
'focus-visible:outline-offset-2 focus:outline-none focus-visible:outline focus-visible:outline-primary'
|
||||
const EXTRA_CLICK_ZONE_CLASSES = 'flex relative before:inset-[-12px] before:absolute before:z-10'
|
||||
@ -80,6 +109,7 @@ const CLASSES_FOR_SIZE: Record<Size, string> = {
|
||||
|
||||
const CLASSES_FOR_VARIANT: Record<Variant, string> = {
|
||||
custom: '',
|
||||
link: 'inline-flex px-0 py-0 rounded-sm text-primary hover:text-primary-90 hover:underline',
|
||||
primary: 'bg-primary text-white hover:bg-primary-90',
|
||||
cancel: 'bg-selected-frame opacity-80 hover:opacity-100',
|
||||
delete: 'bg-delete text-white',
|
||||
@ -103,7 +133,10 @@ const ICON_POSITION: Record<IconPosition, string> = {
|
||||
}
|
||||
|
||||
/** A button allows a user to perform an action, with mouse, touch, and keyboard interactions. */
|
||||
export function Button(props: ButtonProps) {
|
||||
export const Button = React.forwardRef(function Button(
|
||||
props: ButtonProps,
|
||||
ref: React.ForwardedRef<HTMLButtonElement>
|
||||
) {
|
||||
const {
|
||||
className,
|
||||
children,
|
||||
@ -111,22 +144,27 @@ export function Button(props: ButtonProps) {
|
||||
icon,
|
||||
loading = false,
|
||||
isDisabled = loading,
|
||||
type = 'button',
|
||||
iconPosition = 'start',
|
||||
size = 'xsmall',
|
||||
fullWidth = false,
|
||||
rounding = 'large',
|
||||
...ariaButtonProps
|
||||
...ariaProps
|
||||
} = props
|
||||
const focusChildProps = focusHooks.useFocusChild()
|
||||
|
||||
const isLink = ariaProps.href != null
|
||||
|
||||
const Tag = isLink ? aria.Link : aria.Button
|
||||
|
||||
const goodDefaults = isLink ? { rel: 'noopener noreferrer' } : { type: 'button' }
|
||||
|
||||
const classes = clsx(
|
||||
DEFAULT_CLASSES,
|
||||
DISABLED_CLASSES,
|
||||
FOCUS_CLASSES,
|
||||
CLASSES_FOR_VARIANT[variant],
|
||||
CLASSES_FOR_SIZE[size],
|
||||
CLASSES_FOR_ROUNDING[rounding],
|
||||
CLASSES_FOR_VARIANT[variant],
|
||||
{ [LOADING_CLASSES]: loading, [FULL_WIDTH_CLASSES]: fullWidth }
|
||||
)
|
||||
|
||||
@ -150,16 +188,21 @@ export function Button(props: ButtonProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<aria.Button
|
||||
{...aria.mergeProps<aria.ButtonProps>()(ariaButtonProps, focusChildProps, {
|
||||
type,
|
||||
<Tag
|
||||
// @ts-expect-error eventhough typescript is complaining about the type of ariaProps, it is actually correct
|
||||
{...aria.mergeProps()(ariaProps, focusChildProps, goodDefaults, {
|
||||
ref,
|
||||
isDisabled,
|
||||
className: values =>
|
||||
tailwindMerge.twMerge(
|
||||
classes,
|
||||
typeof className === 'function' ? className(values) : className
|
||||
),
|
||||
})}
|
||||
// @ts-expect-error eventhough typescript is complaining about the type of className, it is actually correct
|
||||
className={states =>
|
||||
tailwindMerge.twMerge(
|
||||
classes,
|
||||
// this is safe, because the type of states has correct types outside
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
typeof className === 'function' ? className(states) : className
|
||||
)
|
||||
}
|
||||
>
|
||||
<aria.Text className="relative block">
|
||||
<aria.Text className={clsx('block', { invisible: loading })}>{childrenFactory()}</aria.Text>
|
||||
@ -170,6 +213,6 @@ export function Button(props: ButtonProps) {
|
||||
</aria.Text>
|
||||
)}
|
||||
</aria.Text>
|
||||
</aria.Button>
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -46,9 +46,8 @@ export function Dialog(props: types.DialogProps) {
|
||||
isKeyboardDismissDisabled = false,
|
||||
hideCloseButton = false,
|
||||
className,
|
||||
isOpen = false,
|
||||
defaultOpen = false,
|
||||
onOpenChange = () => {},
|
||||
modalProps,
|
||||
...ariaDialogProps
|
||||
} = props
|
||||
|
||||
@ -60,9 +59,8 @@ export function Dialog(props: types.DialogProps) {
|
||||
isDismissable={isDismissible}
|
||||
isKeyboardDismissDisabled={isKeyboardDismissDisabled}
|
||||
UNSTABLE_portalContainer={root.current}
|
||||
isOpen={isOpen}
|
||||
onOpenChange={onOpenChange}
|
||||
defaultOpen={defaultOpen}
|
||||
{...modalProps}
|
||||
>
|
||||
<aria.Dialog
|
||||
className={tailwindMerge.twMerge(DIALOG_CLASSES, [DIALOG_CLASSES_BY_TYPE[type]], className)}
|
||||
|
@ -14,8 +14,7 @@ export interface DialogProps extends aria.DialogProps {
|
||||
readonly hideCloseButton?: boolean
|
||||
readonly onOpenChange?: (isOpen: boolean) => void
|
||||
readonly isKeyboardDismissDisabled?: boolean
|
||||
readonly isOpen?: boolean
|
||||
readonly defaultOpen?: boolean
|
||||
readonly modalProps?: Pick<aria.ModalOverlayProps, 'className' | 'defaultOpen' | 'isOpen'>
|
||||
}
|
||||
|
||||
/** The props for the DialogTrigger component. */
|
||||
|
@ -19,12 +19,16 @@ import * as errorModule from '#/utilities/error'
|
||||
export function useToastAndLog() {
|
||||
const { getText } = textProvider.useText()
|
||||
const logger = loggerProvider.useLogger()
|
||||
|
||||
return React.useCallback(
|
||||
<K extends text.TextId, T>(
|
||||
textId: K | null,
|
||||
...[error, ...replacements]: text.Replacements[K] extends readonly []
|
||||
? [error?: errorModule.MustNotBeKnown<T>]
|
||||
: [error: errorModule.MustNotBeKnown<T> | null, ...replacements: text.Replacements[K]]
|
||||
? [error?: Error | errorModule.MustNotBeKnown<T>]
|
||||
: [
|
||||
error: Error | errorModule.MustNotBeKnown<T> | null,
|
||||
...replacements: text.Replacements[K],
|
||||
]
|
||||
) => {
|
||||
const messagePrefix =
|
||||
textId == null
|
||||
|
@ -1,6 +1,8 @@
|
||||
/** @file The directory header bar and directory item listing. */
|
||||
import * as React from 'react'
|
||||
|
||||
import * as router from 'react-router-dom'
|
||||
|
||||
import * as appUtils from '#/appUtils'
|
||||
|
||||
import * as eventCallback from '#/hooks/eventCallbackHooks'
|
||||
@ -328,9 +330,12 @@ export default function Drive(props: DriveProps) {
|
||||
<div className={`grid grow place-items-center ${hidden ? 'hidden' : ''}`}>
|
||||
<div className="flex flex-col gap-status-page text-center text-base">
|
||||
{getText('upgradeToUseCloud')}
|
||||
<a className="button self-center bg-help text-white" href="https://enso.org/pricing">
|
||||
<router.Link
|
||||
className="button self-center bg-help text-white"
|
||||
to={appUtils.SUBSCRIBE_PATH}
|
||||
>
|
||||
{getText('upgrade')}
|
||||
</a>
|
||||
</router.Link>
|
||||
{!supportsLocalBackend && (
|
||||
<UnstyledButton
|
||||
className="button self-center bg-help text-white"
|
||||
|
@ -18,6 +18,8 @@ import * as ariaComponents from '#/components/AriaComponents'
|
||||
|
||||
import * as backendModule from '#/services/Backend'
|
||||
|
||||
const PLANS_TO_SPECIFY_ORG_NAME = [backendModule.Plan.team, backendModule.Plan.enterprise]
|
||||
|
||||
/**
|
||||
* Modal for setting the organization name.
|
||||
* Shows up when the user is on the team plan and the organization name is the default.
|
||||
@ -28,13 +30,21 @@ export function SetOrganizationNameModal() {
|
||||
const { backend } = backendProvider.useBackend()
|
||||
const { session } = authProvider.useAuth()
|
||||
|
||||
const userId = (session && 'user' in session && session.user?.userId) ?? null
|
||||
const userPlan = (session && 'user' in session && session.user?.tier) ?? null
|
||||
const userId = session && 'user' in session && session.user?.userId ? session.user.userId : null
|
||||
const userPlan =
|
||||
session && 'user' in session && session.user?.tier != null ? session.user.tier : null
|
||||
|
||||
const queryClient = reactQuery.useQueryClient()
|
||||
const { data } = reactQuery.useSuspenseQuery({
|
||||
queryKey: ['organization', userId],
|
||||
queryFn: () => backend.getOrganization(),
|
||||
queryFn: () => {
|
||||
if (backend.type === backendModule.BackendType.remote) {
|
||||
return backend.getOrganization().catch(() => null)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
staleTime: Infinity,
|
||||
})
|
||||
|
||||
const submit = reactQuery.useMutation({
|
||||
@ -49,7 +59,9 @@ export function SetOrganizationNameModal() {
|
||||
})
|
||||
|
||||
const shouldShowModal =
|
||||
userPlan === backendModule.Plan.team && data?.name?.toString() === 'Test123'
|
||||
userPlan != null &&
|
||||
PLANS_TO_SPECIFY_ORG_NAME.includes(userPlan) &&
|
||||
data?.name?.toString() === ''
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -58,7 +70,7 @@ export function SetOrganizationNameModal() {
|
||||
isDismissible={false}
|
||||
isKeyboardDismissDisabled
|
||||
hideCloseButton
|
||||
isOpen={shouldShowModal}
|
||||
modalProps={{ isOpen: shouldShowModal }}
|
||||
>
|
||||
<aria.Form
|
||||
onSubmit={e => {
|
||||
@ -110,6 +122,7 @@ export function SetOrganizationNameModal() {
|
||||
</ariaComponents.Button>
|
||||
</aria.Form>
|
||||
</ariaComponents.Dialog>
|
||||
|
||||
<router.Outlet context={session} />
|
||||
</>
|
||||
)
|
||||
|
@ -69,14 +69,9 @@ const COMPONENT_PER_PLAN: Record<backendModule.Plan, ComponentForPlan> = {
|
||||
const { getText } = textProvider.useText()
|
||||
|
||||
return (
|
||||
<a
|
||||
href="https://enso.org/pricing"
|
||||
target="_blank"
|
||||
referrerPolicy="no-referrer"
|
||||
className="underline"
|
||||
>
|
||||
<ariaComponents.Button variant="link" href="https://enso.org/pricing" target="_blank">
|
||||
{getText('learnMore')}
|
||||
</a>
|
||||
</ariaComponents.Button>
|
||||
)
|
||||
},
|
||||
pricing: 'soloPlanPricing',
|
||||
@ -105,14 +100,9 @@ const COMPONENT_PER_PLAN: Record<backendModule.Plan, ComponentForPlan> = {
|
||||
const { getText } = textProvider.useText()
|
||||
|
||||
return (
|
||||
<a
|
||||
href="https://enso.org/pricing"
|
||||
target="_blank"
|
||||
referrerPolicy="no-referrer"
|
||||
className="underline"
|
||||
>
|
||||
<ariaComponents.Button variant="link" href="https://enso.org/pricing" target="_blank">
|
||||
{getText('learnMore')}
|
||||
</a>
|
||||
</ariaComponents.Button>
|
||||
)
|
||||
},
|
||||
pricing: 'teamPlanPricing',
|
||||
@ -141,14 +131,9 @@ const COMPONENT_PER_PLAN: Record<backendModule.Plan, ComponentForPlan> = {
|
||||
const { getText } = textProvider.useText()
|
||||
|
||||
return (
|
||||
<a
|
||||
href="https://enso.org/pricing"
|
||||
target="_blank"
|
||||
referrerPolicy="no-referrer"
|
||||
className="underline"
|
||||
>
|
||||
<ariaComponents.Button variant="link" href="https://enso.org/pricing" target="_blank">
|
||||
{getText('learnMore')}
|
||||
</a>
|
||||
</ariaComponents.Button>
|
||||
)
|
||||
},
|
||||
pricing: 'enterprisePlanPricing',
|
||||
@ -158,7 +143,14 @@ const COMPONENT_PER_PLAN: Record<backendModule.Plan, ComponentForPlan> = {
|
||||
submitButton: () => {
|
||||
const { getText } = textProvider.useText()
|
||||
return (
|
||||
<ariaComponents.Button variant="primary" fullWidth size="medium" rounding="full">
|
||||
<ariaComponents.Button
|
||||
fullWidth
|
||||
variant="primary"
|
||||
size="medium"
|
||||
rounding="full"
|
||||
target="_blank"
|
||||
href="mailto:contact@enso.org?subject=Upgrading%20to%20Organization%20Plan"
|
||||
>
|
||||
{getText('contactSales')}
|
||||
</ariaComponents.Button>
|
||||
)
|
||||
|
8
app/ide-desktop/lib/types/modules.d.ts
vendored
8
app/ide-desktop/lib/types/modules.d.ts
vendored
@ -158,8 +158,14 @@ declare module 'create-servers' {
|
||||
|
||||
/** Configuration options for `create-servers`. */
|
||||
interface CreateServersOptions {
|
||||
readonly http: number
|
||||
readonly http?: number
|
||||
readonly handler: http.RequestListener
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
readonly https?: {
|
||||
readonly port: number
|
||||
readonly key: string
|
||||
readonly cert: string
|
||||
}
|
||||
}
|
||||
|
||||
/** An error passed to a callback when a HTTP request fails. */
|
||||
|
32
package-lock.json
generated
32
package-lock.json
generated
@ -181,6 +181,7 @@
|
||||
"create-servers": "3.2.0",
|
||||
"electron-is-dev": "^2.0.0",
|
||||
"mime-types": "^2.1.35",
|
||||
"mkcert": "3.2.0",
|
||||
"opener": "^1.5.2",
|
||||
"string-length": "^5.0.1",
|
||||
"tar": "^6.1.13",
|
||||
@ -14915,6 +14916,29 @@
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/mkcert": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mkcert/-/mkcert-3.2.0.tgz",
|
||||
"integrity": "sha512-026Eivq9RoOjOuLJGzbhGwXUAjBxRX11Z7Jbm4/7lqT/Av+XNy9SPrJte6+UpEt7i+W3e/HZYxQqlQcqXZWSzg==",
|
||||
"dependencies": {
|
||||
"commander": "^11.0.0",
|
||||
"node-forge": "^1.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"mkcert": "dist/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/mkcert/node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
@ -15133,6 +15157,14 @@
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz",
|
||||
|
Loading…
Reference in New Issue
Block a user