Skip to content

Commit 0830c08

Browse files
Merge remote-tracking branch 'origin/develop' into wip/jtulach/AverageOverByteBuffer13851
2 parents 3fcf693 + 99916d5 commit 0830c08

File tree

65 files changed

+1356
-336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1356
-336
lines changed

CHANGELOG.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
is included][14028]
1515
- [Function docs in autocomplete in table expressions][14059]
1616
- [Many CLI arguments removed][14069]
17+
- [Support opening project by clicking on link in documentation][14136]
1718
- [Images may be added to assets descriptions][14247]
1819
- [Dragging edges from plus button on nodes is now possible][14246]
1920
- [JSON and SQL visualizations' content may be now selected and copied][14262]
@@ -27,6 +28,8 @@
2728
top.
2829
- [Context menu for connections][14325].
2930
- [Warnings and Errors no longer become transparent][14388]
31+
- [GeoMap visualization is now working without need of Mapbox Token in
32+
environment][14429]
3033

3134
[13685]: https://github.com/enso-org/enso/pull/13685
3235
[13658]: https://github.com/enso-org/enso/pull/13658
@@ -39,6 +42,7 @@
3942
[13976]: https://github.com/enso-org/enso/pull/13976
4043
[14059]: https://github.com/enso-org/enso/pull/14059
4144
[14069]: https://github.com/enso-org/enso/pull/14069
45+
[14136]: https://github.com/enso-org/enso/pull/14136
4246
[14247]: https://github.com/enso-org/enso/pull/14247
4347
[14262]: https://github.com/enso-org/enso/pull/14262
4448
[14246]: https://github.com/enso-org/enso/pull/14246
@@ -49,6 +53,7 @@
4953
[14267]: https://github.com/enso-org/enso/pull/14267
5054
[14325]: https://github.com/enso-org/enso/pull/14325
5155
[14388]: https://github.com/enso-org/enso/pull/14388
56+
[14429]: https://github.com/enso-org/enso/pull/14429
5257

5358
#### Enso Standard Library
5459

@@ -74,9 +79,11 @@
7479
- [Initial Spatial support within DuckDB][14331]
7580
- [Add email SMTP support][14350]
7681
- [Read files into DuckDB both spatial and not.][14367]
77-
- [Implement Text_Column to_case for DB backends][14386]
78-
- [Implement bulk loading to DuckDB][14402]
79-
- [Initial file writing from DuckDB][14421]
82+
- [Implement Text_Column to_case for DB backends.][14386]
83+
- [Implement bulk loading to DuckDB.][14402]
84+
- [Implement `Text_Column.text_mid` for in-memory and database backends.][14420]
85+
- [Initial file writing from DuckDB.][14421]
86+
- [Parquet file reading and writing, DuckDB formats.][14427]
8087

8188
[13769]: https://github.com/enso-org/enso/pull/13769
8289
[14026]: https://github.com/enso-org/enso/pull/14026
@@ -101,7 +108,9 @@
101108
[14367]: https://github.com/enso-org/enso/pull/14367
102109
[14386]: https://github.com/enso-org/enso/pull/14386
103110
[14402]: https://github.com/enso-org/enso/pull/14402
111+
[14420]: https://github.com/enso-org/enso/pull/14420
104112
[14421]: https://github.com/enso-org/enso/pull/14421
113+
[14427]: https://github.com/enso-org/enso/pull/14427
105114

106115
#### Enso Language & Runtime
107116

app/common/src/services/Backend.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,17 @@ export interface CreateCustomerPortalSessionResponse {
635635
/** Response from the "path/resolve" endpoint. */
636636
export interface PathResolveResponse extends Omit<AnyRealAsset, 'type' | 'ensoPath'> {}
637637

638+
/** Whether a type is `any`. */
639+
type IsAny<T> = 0 extends 1 & T ? true : false
640+
638641
/** Response from "assets/${assetId}" endpoint. */
639642
export type AssetDetailsResponse<Id extends AssetId> =
640-
| (Asset<AssetTypeFromId<Id>> & { readonly metadataId: MetadataId })
641-
| null
643+
// `T extends T` where `T` is a type parameter is a trick to distribute union values,
644+
// evaluating the conditional type for each member of the union type,
645+
// and then resolving to a union of the results of this operation.
646+
IsAny<Id> extends true ? AssetDetailsResponse<AssetId>
647+
: | (Id extends Id ? AnyAsset<AssetTypeFromId<Id>> & { readonly metadataId: MetadataId } : never)
648+
| null
642649

643650
/** Whether the user is on a plan with multiple seats (i.e. a plan that supports multiple users). */
644651
export function isUserOnPlanWithMultipleSeats(user: User) {
@@ -1648,6 +1655,15 @@ export function isNewTitleUnique(
16481655
)
16491656
}
16501657

1658+
export const MAPBOX_TOKEN_SCHEMA = z.object({
1659+
token: z.string(),
1660+
expires: z
1661+
.string()
1662+
.datetime({ offset: true })
1663+
.transform((str) => new Date(str)),
1664+
})
1665+
export type MapboxToken = z.infer<typeof MAPBOX_TOKEN_SCHEMA>
1666+
16511667
/** Network error class. */
16521668
export class NetworkError extends Error {
16531669
/**
@@ -2014,6 +2030,8 @@ export abstract class Backend {
20142030
abstract createApiKey(body: CreateApiKeyRequestBody): Promise<ApiKey>
20152031
/** Delete a API key for the current user. */
20162032
abstract deleteApiKey(apiKeyId: ApiKeyId): Promise<void>
2033+
/** Retrieve Mapbox token for the current user. */
2034+
abstract getMapboxToken(): Promise<MapboxToken>
20172035

20182036
/** Throw a {@link backend.NotAuthorizedError} if the response is a 401 Not Authorized status code. */
20192037
private async checkForAuthenticationError<T>(
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { newtypeConstructor, type Newtype } from '../../utilities/data/newtype.js'
2+
3+
/** The path of this asset, including the root directory. */
4+
export type EnsoPath = Newtype<string, 'EnsoPath'>
5+
export const EnsoPath = newtypeConstructor<EnsoPath>()
6+
7+
/** The path string of this asset, including the root directory. */
8+
export type EnsoPathValue = Newtype<string, 'EnsoPathValue'>
9+
export const EnsoPathValue = newtypeConstructor<EnsoPathValue>()
10+
11+
/** Checks if paths are equal, ignoring subsequent `/`. */
12+
export function ensoPathEq(a: EnsoPath, b: EnsoPath) {
13+
const normalize = (x: EnsoPath) => x.replaceAll(/\/+/g, '/')
14+
return normalize(a) === normalize(b)
15+
}

app/common/src/services/Backend/remoteBackendPaths.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export const CREATE_API_KEY_PATH = 'credentials'
103103
export function deleteApiKeyPath(apiKeyId: ApiKeyId) {
104104
return `credentials/${apiKeyId}`
105105
}
106+
export const GET_MAPBOX_TOKEN_PATH = 'mapbox/token'
106107

107108
/** Relative HTTP path to the "cancel subscription" endpoint of the Cloud backend API. */
108109
export function cancelSubscriptionPath(subscriptionId: SubscriptionId) {

app/common/src/services/Backend/types.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { newtypeConstructor, type Newtype } from '../../utilities/data/newtype.js'
22
import type { IdType } from '../Backend.js'
3+
export { EnsoPath, EnsoPathValue } from './ensoPath.js'
34

45
/** A KSUID. */
56
export type KSUID = Newtype<string, 'KSUID'>
@@ -161,14 +162,6 @@ export const ParentsPath = newtypeConstructor<ParentsPath>()
161162
export type VirtualParentsPath = Newtype<string, 'VirtualParentsPath'>
162163
export const VirtualParentsPath = newtypeConstructor<VirtualParentsPath>()
163164

164-
/** The path of this asset, including the root directory. */
165-
export type EnsoPath = Newtype<string, 'EnsoPath'>
166-
export const EnsoPath = newtypeConstructor<EnsoPath>()
167-
168-
/** The path string of this asset, including the root directory. */
169-
export type EnsoPathValue = Newtype<string, 'EnsoPathValue'>
170-
export const EnsoPathValue = newtypeConstructor<EnsoPathValue>()
171-
172165
/** A pagination token for an arbitrary endpoint. */
173166
export type PaginationToken = Newtype<string, 'PaginationToken'>
174167
export const PaginationToken = newtypeConstructor<PaginationToken>()

app/common/src/services/LocalBackend.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ export class LocalBackend extends backend.Backend {
778778

779779
/** Resolve path to asset. In case of LocalBackend, this is just the filesystem path. */
780780
override resolveEnsoPath(path: backend.EnsoPath): Promise<backend.PathResolveResponse> {
781-
const { directoryPath } = getDirectoryAndName(Path(path as string))
781+
const { directoryPath } = getDirectoryAndName(Path(String(path)))
782782
return this.findAsset(directoryPath, 'ensoPath', path)
783783
}
784784

@@ -1123,6 +1123,11 @@ export class LocalBackend extends backend.Backend {
11231123
return this.invalidOperation()
11241124
}
11251125

1126+
/** Invalid operation */
1127+
override getMapboxToken() {
1128+
return this.invalidOperation()
1129+
}
1130+
11261131
/** Find asset details using directory listing. */
11271132
private async findAsset<Key extends keyof backend.AnyAsset>(
11281133
directory: Path,

app/common/src/services/RemoteBackend.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,10 @@ export class RemoteBackend extends backend.Backend {
208208
params: backend.UploadPictureRequestParams,
209209
file: Blob,
210210
): Promise<backend.User> {
211-
const paramsString = new URLSearchParams({
211+
const paramsString = new URLSearchParams(
212212
// eslint-disable-next-line camelcase
213-
...(params.fileName != null ? { file_name: params.fileName } : {}),
214-
}).toString()
213+
params.fileName != null ? { file_name: params.fileName } : {},
214+
).toString()
215215
const path = `${remoteBackendPaths.UPLOAD_USER_PICTURE_PATH}?${paramsString}`
216216
const response = await this.putBinary<backend.User>(path, file)
217217
if (!response.ok) {
@@ -279,10 +279,10 @@ export class RemoteBackend extends backend.Backend {
279279
params: backend.UploadPictureRequestParams,
280280
file: Blob,
281281
): Promise<backend.OrganizationInfo> {
282-
const paramsString = new URLSearchParams({
282+
const paramsString = new URLSearchParams(
283283
// eslint-disable-next-line camelcase
284-
...(params.fileName != null ? { file_name: params.fileName } : {}),
285-
}).toString()
284+
params.fileName != null ? { file_name: params.fileName } : {},
285+
).toString()
286286
const path = `${remoteBackendPaths.UPLOAD_ORGANIZATION_PICTURE_PATH}?${paramsString}`
287287
const response = await this.putBinary<backend.OrganizationInfo>(path, file)
288288
if (!response.ok) {
@@ -808,9 +808,9 @@ export class RemoteBackend extends backend.Backend {
808808
params: backend.GetProjectSessionLogsRequestParams,
809809
title: string,
810810
): Promise<backend.ProjectSessionLogs> {
811-
const queryParams = new URLSearchParams({
812-
...(params.scrollId != null ? { scrollId: params.scrollId } : {}),
813-
})
811+
const queryParams = new URLSearchParams(
812+
params.scrollId != null ? { scrollId: params.scrollId } : {},
813+
)
814814
const path = remoteBackendPaths.getProjectSessionLogsPath(projectSessionId)
815815
const response = await this.get<backend.ProjectSessionLogs>(path, queryParams)
816816
if (!response.ok) {
@@ -1270,6 +1270,16 @@ export class RemoteBackend extends backend.Backend {
12701270
}
12711271
}
12721272

1273+
/** Retrieve Mapbox token for the current user. */
1274+
override async getMapboxToken(): Promise<backend.MapboxToken> {
1275+
const response = await this.get(remoteBackendPaths.GET_MAPBOX_TOKEN_PATH)
1276+
if (!response.ok) {
1277+
return await this.throw(response, 'getMapboxTokenBackendError')
1278+
} else {
1279+
return backend.MAPBOX_TOKEN_SCHEMA.parse(await response.json())
1280+
}
1281+
}
1282+
12731283
/**
12741284
* Cancel given subscription.
12751285
* @throws An error if a non-successful status code (not 200-299) was received.
@@ -1329,10 +1339,7 @@ export class RemoteBackend extends backend.Backend {
13291339
{
13301340
message,
13311341
projectId,
1332-
metadata: {
1333-
timestamp: new Date().toISOString(),
1334-
...(metadata ?? {}),
1335-
},
1342+
metadata: { timestamp: new Date().toISOString(), ...metadata },
13361343
},
13371344
{
13381345
keepalive: true,
@@ -1471,9 +1478,10 @@ export class RemoteBackend extends backend.Backend {
14711478

14721479
/** Resolve asset metadata from an enso path. */
14731480
override async resolveEnsoPath(path: backend.EnsoPath): Promise<backend.PathResolveResponse> {
1481+
const effectivePath = backend.EnsoPath(path.replace(/%20/g, ' '))
14741482
const response = await this.get<backend.Asset<backend.RealAssetType>>(
14751483
remoteBackendPaths.RESOLVE_ENSO_PATH,
1476-
{ path },
1484+
{ path: effectivePath },
14771485
)
14781486

14791487
if (!response.ok) return this.throw(response, 'resolveEnsoPathBackendError')

app/common/src/text/english.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,10 +1095,6 @@
10951095
"ensoDevtoolsFeatureFlags": "Feature Flags",
10961096
"ensoDevtoolsFeatureFlags.showDeveloperIds": "Show Developer Ids",
10971097
"ensoDevtoolsFeatureFlags.showDeveloperIdsDescription": "Show object ids for debugging purposes.",
1098-
"ensoDevtoolsFeatureFlags.overrideProfilePicture": "Override Profile Picture",
1099-
"ensoDevtoolsFeatureFlags.overrideProfilePictureDescription": "Override the user's profile picture with a fixed image.",
1100-
"ensoDevtoolsFeatureFlags.multiplyUserList": "Multiply User List",
1101-
"ensoDevtoolsFeatureFlags.multiplyUserListDescription": "Multiply each user in the user list to simulate more users.",
11021098
"ensoDevtoolsFeatureFlags.enableMultitabs": "Enable Multitabs",
11031099
"ensoDevtoolsFeatureFlags.enableMultitabsDescription": "Allow multiple asset panels to be open at the same time.",
11041100
"ensoDevtoolsFeatureFlags.enableAssetsTableBackgroundRefresh": "Enable Assets Table Background Refresh",
@@ -1269,6 +1265,7 @@
12691265
"listApiKeysBackendError": "Could not list API keys.",
12701266
"createApiKeyBackendError": "Could not create API key.",
12711267
"deleteApiKeyBackendError": "Could not delete API key.",
1268+
"getMapboxTokenBackendError": "Could not retrieve Mapbox token.",
12721269
"keyId": "Access key",
12731270
"secretId": "Secret access key",
12741271
"accessKeyAlert": "If you lose or forget your secret access key, you cannot retrieve it. Instead, create a new access key and make the old key inactive.",

app/gui/src/components/AppContainer/AppContainer.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script lang="ts">
2+
import { ModalWrapper as ModalWrapperReact } from '#/components/ModalWrapper'
23
import type { PaywallFeatureName } from '#/hooks/billing'
34
import { UserBar as UserBarReact } from '#/pages/dashboard/UserBar'
45
import CommandPalette from '$/components/CommandPalette.vue'
@@ -25,6 +26,7 @@ import { Drive, Settings } from './reactTabs'
2526
import RightPanel from './RightPanel.vue'
2627
import SelectableTab from './SelectableTab.vue'
2728
29+
const ModalWrapper = reactComponent(ModalWrapperReact)
2830
const UserBar = reactComponent(UserBarReact)
2931
</script>
3032

@@ -130,6 +132,7 @@ onUnmounted(() => {
130132
<div class="TabView">
131133
<CommandPalette />
132134
<ContainerProviderForReact>
135+
<ModalWrapper />
133136
<div class="bar">
134137
<div role="tablist" class="tablist">
135138
<SelectableTab
@@ -176,10 +179,7 @@ onUnmounted(() => {
176179
<Drive v-if="tab === 'drive'" />
177180
</KeepAlive>
178181
<KeepAlive v-for="project in projectTabs" :key="project.state.info.id">
179-
<ProjectView
180-
v-if="tab === project.state.info.ensoPath"
181-
:projectId="project.state.info.id"
182-
/>
182+
<ProjectView v-if="project.shown.value" :projectId="project.state.info.id" />
183183
</KeepAlive>
184184
<KeepAlive>
185185
<Settings v-if="tab === 'settings'" />

app/gui/src/dashboard/components/Devtools/EnsoDevtoolsImpl.tsx

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ function DeveloperOverrideEntry(props: DeveloperOverrideEntryProps) {
6868

6969
/** A display of current developer overrides. */
7070
export function EnsoDevStatus() {
71-
const queryClient = useQueryClient()
7271
const { getText } = useText()
7372
const showEnsoDevtools = useShowEnsoDevtools()
7473
const versionCheckerEnabled = useEnableVersionChecker() ?? false
@@ -81,8 +80,6 @@ export function EnsoDevStatus() {
8180
assetsTableBackgroundRefreshInterval,
8281
enableCloudExecution,
8382
enableAdvancedProjectExecutionOptions,
84-
overrideProfilePicture,
85-
multiplyUserList,
8683
listDirectoryPageSize,
8784
getLogEventsPageSize,
8885
fileChunkUploadPoolSize,
@@ -111,8 +108,6 @@ export function EnsoDevStatus() {
111108
assetsTableBackgroundRefreshInterval !== DEFAULT_ASSETS_TABLE_REFRESH_INTERVAL_MS ||
112109
!enableCloudExecution ||
113110
showDeveloperIds ||
114-
overrideProfilePicture ||
115-
multiplyUserList ||
116111
enableMultitabs ||
117112
enableAdvancedProjectExecutionOptions ||
118113
listDirectoryPageSize !== DEFAULT_LIST_DIRECTORY_PAGE_SIZE ||
@@ -190,25 +185,6 @@ export function EnsoDevStatus() {
190185
{getText('showingDeveloperIds')}
191186
</DeveloperOverrideEntry>
192187
)}
193-
{overrideProfilePicture && (
194-
<DeveloperOverrideEntry
195-
reset={() => {
196-
setFeatureFlag('overrideProfilePicture', false)
197-
}}
198-
>
199-
{getText('overridingProfilePicture')}
200-
</DeveloperOverrideEntry>
201-
)}
202-
{multiplyUserList && (
203-
<DeveloperOverrideEntry
204-
reset={async () => {
205-
setFeatureFlag('multiplyUserList', false)
206-
await queryClient.invalidateQueries({ queryKey: ['remote', 'listUsers'] })
207-
}}
208-
>
209-
{getText('multiplyingUserList')}
210-
</DeveloperOverrideEntry>
211-
)}
212188
{enableMultitabs && (
213189
<DeveloperOverrideEntry
214190
reset={() => {
@@ -427,27 +403,6 @@ export function EnsoDevtools() {
427403
setFeatureFlag('showDeveloperIds', value)
428404
}}
429405
/>
430-
<Switch
431-
form={form}
432-
name="overrideProfilePicture"
433-
label={getText('ensoDevtoolsFeatureFlags.overrideProfilePicture')}
434-
description={getText(
435-
'ensoDevtoolsFeatureFlags.overrideProfilePictureDescription',
436-
)}
437-
onChange={(value) => {
438-
setFeatureFlag('overrideProfilePicture', value)
439-
}}
440-
/>
441-
<Switch
442-
form={form}
443-
name="multiplyUserList"
444-
label={getText('ensoDevtoolsFeatureFlags.multiplyUserList')}
445-
description={getText('ensoDevtoolsFeatureFlags.multiplyUserListDescription')}
446-
onChange={async (value) => {
447-
setFeatureFlag('multiplyUserList', value)
448-
await queryClient.invalidateQueries({ queryKey: ['remote', 'listUsers'] })
449-
}}
450-
/>
451406
<Switch
452407
form={form}
453408
name="enableMultitabs"

0 commit comments

Comments
 (0)