Skip to content
Draft
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
2 changes: 1 addition & 1 deletion OMICRON_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2b4ea30370131dc1dce31e52dc62f6f5b1e66552
a34b8db4fd12ea9e982d5eb694040062d8d8d243
59 changes: 45 additions & 14 deletions app/api/__generated__/Api.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/api/__generated__/OMICRON_VERSION

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions app/api/__generated__/msw-handlers.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 15 additions & 7 deletions app/api/__generated__/validate.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions app/components/StateBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,9 @@ export const DiskTypeBadge = (props: { diskType: DiskType; className?: string })
{props.diskType}
</Badge>
)

export const ReadOnlyBadge = () => (
<Badge color="neutral" className="relative">
Read only
</Badge>
)
59 changes: 41 additions & 18 deletions app/forms/disk-create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
type Image,
} from '@oxide/api'

import { CheckboxField } from '~/components/form/fields/CheckboxField'
import { DescriptionField } from '~/components/form/fields/DescriptionField'
import { DiskSizeField } from '~/components/form/fields/DiskSizeField'
import { toImageComboboxItem } from '~/components/form/fields/ImageSelectField'
Expand Down Expand Up @@ -245,7 +246,13 @@ const DiskSourceField = ({
// need to include blockSize when switching back to blank. other
// source types get their required fields from form inputs
setDiskSource(
newType === 'blank' ? blankDiskSource : ({ type: newType } as DiskSource)
newType === 'blank'
? blankDiskSource
: newType === 'snapshot'
? ({ type: 'snapshot', readOnly: false } as DiskSource)
: newType === 'image'
? ({ type: 'image', readOnly: false } as DiskSource)
: ({ type: newType } as DiskSource)
)
}}
>
Expand All @@ -271,25 +278,41 @@ const DiskSourceField = ({
/>
)}
{diskSource.type === 'image' && (
<ListboxField
control={control}
name="diskBackend.diskSource.imageId"
label="Source image"
placeholder="Select an image"
isLoading={areImagesLoading}
items={images.map((i) => toImageComboboxItem(i, true))}
required
onChange={(id) => {
const image = images.find((i) => i.id === id)!
const imageSizeGiB = image.size / GiB
if (diskSizeField.value < imageSizeGiB) {
diskSizeField.onChange(diskSizeNearest10(imageSizeGiB))
}
}}
/>
<>
<ListboxField
control={control}
name="diskBackend.diskSource.imageId"
label="Source image"
placeholder="Select an image"
isLoading={areImagesLoading}
items={images.map((i) => toImageComboboxItem(i, true))}
required
onChange={(id) => {
const image = images.find((i) => i.id === id)!
const imageSizeGiB = image.size / GiB
if (diskSizeField.value < imageSizeGiB) {
diskSizeField.onChange(diskSizeNearest10(imageSizeGiB))
}
}}
/>
<div className="mt-2">
<CheckboxField name="diskBackend.diskSource.readOnly" control={control}>
Make disk read-only
</CheckboxField>
</div>
</>
)}

{diskSource.type === 'snapshot' && <SnapshotSelectField control={control} />}
{diskSource.type === 'snapshot' && (
<>
<SnapshotSelectField control={control} />
<div className="mt-2">
<CheckboxField name="diskBackend.diskSource.readOnly" control={control}>
Make disk read-only
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Make disk" is strange? Maybe just "Read-only"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put that in there tentatively because when it was just read-only, it wasn't clear enough that read-only refers to the resulting disk. So I think we need something more than read-only. Unless we just make the label "Read only" and we put help text in there that says "Instances won't be able to write to this disk" or something. I am also slightly torn about the hyphen. Generally I feel like hyphen is right for regular copy, but when it's just "Read-only" by itself it looks bad.

</CheckboxField>
</div>
</>
)}
</div>
</>
)
Expand Down
2 changes: 1 addition & 1 deletion app/forms/instance-create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const getBootDiskAttachment = (
size: values.bootDiskSize * GiB,
diskBackend: {
type: 'distributed',
diskSource: { type: 'image', imageId: source },
diskSource: { type: 'image', imageId: source, readOnly: false },
},
}
}
Expand Down
3 changes: 3 additions & 0 deletions app/pages/project/disks/DiskDetailSideModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ export function DiskDetailSideModal({
<PropertiesTable.Row label="Snapshot ID">
{disk.snapshotId ?? <EmptyCell />}
</PropertiesTable.Row>
<PropertiesTable.Row label="Read only">
{disk.readOnly ? 'Yes' : 'No'}
</PropertiesTable.Row>
<PropertiesTable.Row label="Block size">
{disk.blockSize.toLocaleString()} bytes
</PropertiesTable.Row>
Expand Down
9 changes: 7 additions & 2 deletions app/pages/project/disks/DisksPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { Storage16Icon, Storage24Icon } from '@oxide/design-system/icons/react'

import { DocsPopover } from '~/components/DocsPopover'
import { HL } from '~/components/HL'
import { DiskStateBadge, DiskTypeBadge } from '~/components/StateBadge'
import { DiskStateBadge, DiskTypeBadge, ReadOnlyBadge } from '~/components/StateBadge'
import { makeCrumb } from '~/hooks/use-crumbs'
import { getProjectSelector, useProjectSelector } from '~/hooks/use-params'
import { confirmDelete } from '~/stores/confirm-delete'
Expand Down Expand Up @@ -147,7 +147,12 @@ export default function DisksPage() {
useMemo(
() => [
colHelper.accessor('name', {
cell: makeLinkCell((name) => pb.disk({ project, disk: name })),
cell: (info) => (
<span className="flex items-center gap-2">
{makeLinkCell((name) => pb.disk({ project, disk: name }))(info)}
{info.row.original.readOnly && <ReadOnlyBadge />}
</span>
),
}),
// sneaky: rather than looking at particular states, just look at
// whether it has an instance field
Expand Down
11 changes: 7 additions & 4 deletions app/pages/project/instances/StorageTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import { Storage24Icon } from '@oxide/design-system/icons/react'

import { HL } from '~/components/HL'
import { DiskStateBadge, DiskTypeBadge } from '~/components/StateBadge'
import { DiskStateBadge, DiskTypeBadge, ReadOnlyBadge } from '~/components/StateBadge'
import { AttachDiskModalForm } from '~/forms/disk-attach'
import { CreateDiskSideModalForm } from '~/forms/disk-create'
import { getInstanceSelector, useInstanceSelector } from '~/hooks/use-params'
Expand Down Expand Up @@ -85,9 +85,12 @@ export default function StorageTab() {
colHelper.accessor('name', {
header: 'Disk',
cell: (info) => (
<ButtonCell onClick={() => setSelectedDisk(info.row.original)}>
{info.getValue()}
</ButtonCell>
<span className="flex items-center gap-2">
<ButtonCell onClick={() => setSelectedDisk(info.row.original)}>
{info.getValue()}
</ButtonCell>
{info.row.original.readOnly && <ReadOnlyBadge />}
</span>
),
}),
colHelper.accessor('diskType', {
Expand Down
Loading
Loading