Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sy 1141 remove view details from range toolbar context menu #826

Merged
Merged
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
80 changes: 51 additions & 29 deletions .github/PULL_REQUEST_TEMPLATE/rc.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,35 +109,57 @@ I can successfully:

I can successfully:

- [ ] Open create range dialog from command search bar.
- [ ] Open create range dialog from range toolbar.
- [ ] Open create range dialog from context menu in range toolbar.
- [ ] Create a new local range.
- [ ] Create a new persisted range.
- [ ] Set a parent range for a range.
- [ ] Attach labels to a range.
- [ ] Open the range overview dialog from the resources view.
- [ ] Edit range properties from the overview dialog.
- [ ] Edit meta-data properties on the range.
- [ ] Add child ranges to a range.
- [ ] Navigate to and from child ranges on a range.
- [ ] Make a change to the range in the edit dialog and see the changes propagate to the
overview dialog.
- [ ] Save a local range to Synnax in the range toolbar.
- [ ] Switch the active range in the range toolbar.
- [ ] Load a local range from the search bar.
- [ ] Load a persisted range from the search bar.
- [ ] Rename a range from the range toolbar.
- [ ] Edit a range from the range toolbar.
- [ ] Remove a range from the range toolbar.
- [ ] Delete a persisted range from the range toolbar.
- [ ] Delete a range in the resources view.
- [ ] Delete multiple ranges in the resources view.
- [ ] Set a range as an active range from the resources view.
- [ ] Edit a range from the resources view.
- [ ] Add a range to a plot from the resources view.
- [ ] Copy a link to a range and open it from the resources view.
- [ ] Rename a range from the range toolbar.
- [ ] Create Range Modal
- [ ] Create a new local range.
- [ ] Create a new persisted range.
- [ ] Set parent range
- [ ] Add labels
- [ ] Rename existing range
- [ ] Change times on existing range
- [ ] Range Layout
- [ ] Rename range.
- [ ] Rename range from tab.
- [ ] Change start and end times.
- [ ] Add labels.
- [ ] Set metadata.
- [ ] Delete metadata.
- [ ] Add child ranges.
- [ ] Open snapshots.
- [ ] Navigate to and from child ranges
- [ ] Search and Command Palette
- [ ] Open an existing range window
- [ ] Open create range dialog
- [ ] Range Toolbar
- [ ] Open create range modal from toolbar link when no range exists
- [ ] Switch the active range by clicking
- [ ] Context Menu
- [ ] Open create range modal
- [ ] Rename range
- [ ] Set active range
- [ ] Open create range modal with child range
- [ ] Add to active line plot
- [ ] Add to new line plot
- [ ] Remove from range toolbar
- [ ] Delete persisted range
- [ ] Copy link of persisted range
- [ ] Save local range to Synnax
- [ ] Resources Toolbar
- [ ] Open the range overview dialog by clicking on a range
- [ ] Context Menu
- [ ] Set active range
- [ ] Rename range
- [ ] Open create range modal with child range
- [ ] Group ranges
- [ ] Add to active line plot
- [ ] Add multiple ranges to active line plot
- [ ] Add to new line plot
- [ ] Add multiple ranges to new line plot
- [ ] Delete range
- [ ] Delete multiple ranges
- [ ] Copy link to range
- [ ] Open a range from its url
- [ ] Make changes to a range with resources toolbar, overview, and ranges toolbar open
and see changes propagate to all three.

### Channels

Expand Down
2 changes: 1 addition & 1 deletion console/src/lineplot/LinePlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ const Loaded = ({ layoutKey }: { layoutKey: string }): ReactElement => {
break;
case "range":
placer(
Range.createEditLayout({
Range.createLayout({
initial: {
timeRange: {
start: Number(timeRange.start.valueOf()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* included in the file licenses/APL.txt.
*/

.console-range-edit-layout {
padding-top: 2rem;
.console-range-create-layout {
padding-top: 2rem;
height: 100%;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,25 @@
// License, use of this software will be governed by the Apache License, Version 2.0,
// included in the file licenses/APL.txt.

import "@/range/EditLayout.css";
import "@/range/CreateLayout.css";

import {
ontology,
ranger,
TimeRange,
TimeStamp,
UnexpectedError,
} from "@synnaxlabs/client";
import { Icon, Logo } from "@synnaxlabs/media";
import { ontology, type ranger, TimeRange, TimeStamp } from "@synnaxlabs/client";
import { Icon } from "@synnaxlabs/media";
import {
Align,
Button,
Form,
Icon as PIcon,
Input,
Nav,
Ranger,
Status,
Synnax,
Text,
Triggers,
} from "@synnaxlabs/pluto";
import { Input } from "@synnaxlabs/pluto/input";
import { deep, primitiveIsZero } from "@synnaxlabs/x";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useMutation } from "@tanstack/react-query";
import { type ReactElement, useCallback, useRef } from "react";
import { useDispatch } from "react-redux";
import { v4 as uuidv4 } from "uuid";
Expand All @@ -40,7 +34,6 @@ import { z } from "zod";
import { CSS } from "@/css";
import { Label } from "@/label";
import { Layout } from "@/layout";
import { useSelect } from "@/range/selectors";
import { add } from "@/range/slice";

const formSchema = z.object({
Expand All @@ -51,29 +44,31 @@ const formSchema = z.object({
parent: z.string().optional(),
});

type Args = Partial<z.infer<typeof formSchema>>;
type FormProps = z.infer<typeof formSchema>;

type Args = Partial<FormProps>;

export const EDIT_LAYOUT_TYPE = "editRange";
export const CREATE_LAYOUT_TYPE = "editRange";

const SAVE_TRIGGER: Triggers.Trigger = ["Control", "Enter"];

interface CreateEditLayoutProps extends Partial<Layout.State> {
interface CreateLayoutProps extends Partial<Layout.State> {
initial?: Partial<Args>;
}

export const createEditLayout = ({
export const createLayout = ({
name,
initial = {},
window,
...rest
}: CreateEditLayoutProps): Layout.State => ({
}: CreateLayoutProps): Layout.State => ({
...rest,
key: EDIT_LAYOUT_TYPE,
type: EDIT_LAYOUT_TYPE,
windowKey: EDIT_LAYOUT_TYPE,
key: CREATE_LAYOUT_TYPE,
type: CREATE_LAYOUT_TYPE,
windowKey: CREATE_LAYOUT_TYPE,
icon: "Range",
location: "modal",
name: name ?? (initial.key != null ? "Range.Edit" : "Range.Create"),
name: name ?? "Range.Create",
window: {
resizable: false,
size: { height: 370, width: 700 },
Expand All @@ -83,99 +78,55 @@ export const createEditLayout = ({
args: initial,
});

type DefineRangeFormProps = z.infer<typeof formSchema>;

const parentRangeIcon = (
<PIcon.Icon bottomRight={<Icon.Arrow.Up />}>
<Icon.Range />
</PIcon.Icon>
);

export const Edit = (props: Layout.RendererProps): ReactElement => {
export const Create = (props: Layout.RendererProps): ReactElement => {
const { layoutKey } = props;
const now = useRef(Number(TimeStamp.now().valueOf())).current;
const args = Layout.useSelectArgs<Args>(layoutKey);
const range = useSelect(args.key);
const client = Synnax.use();
const isCreate = args.key == null;
const isEdit = !isCreate && (range == null || range.persisted);
const initialValues = useQuery<DefineRangeFormProps>({
queryKey: ["range-edit", args],
queryFn: async () => {
if (isCreate)
return {
name: "",
labels: [],
timeRange: { start: now, end: now },
parent: "",
...args,
};
if (range == null || range.persisted) {
const key = args.key as string;
if (client == null) throw new UnexpectedError("Client is not available");
const rng = await client.ranges.retrieve(key);
const parent = await rng.retrieveParent();
const labels = await rng.labels();
return {
key: rng.key,
name: rng.name,
timeRange: rng.timeRange.numeric,
labels: labels.map((l) => l.key),
parent: parent?.key ?? "",
};
}
if (range.variant !== "static") throw new UnexpectedError("Range is not static");
return {
key: range.key,
name: range.name,
timeRange: range.timeRange,
labels: [],
parent: "",
};
},
});
if (initialValues.isPending) return <Logo.Watermark variant="loader" />;
if (initialValues.isError) throw initialValues.error;
return (
<EditLayoutForm
isRemoteEdit={isEdit}
initialValues={initialValues.data}
{...props}
/>
);
const initialValues: FormProps = {
name: "",
labels: [],
timeRange: { start: now, end: now },
parent: "",
...args,
};

return <CreateLayoutForm initialValues={initialValues} {...props} />;
};

interface EditLayoutFormProps extends Layout.RendererProps {
initialValues: DefineRangeFormProps;
isRemoteEdit: boolean;
interface CreateLayoutFormProps extends Layout.RendererProps {
initialValues: FormProps;
onClose: () => void;
}

const EditLayoutForm = ({
const CreateLayoutForm = ({
initialValues,
isRemoteEdit,
onClose,
}: EditLayoutFormProps): ReactElement => {
}: CreateLayoutFormProps): ReactElement => {
const methods = Form.use({ values: deep.copy(initialValues), schema: formSchema });
const dispatch = useDispatch();
const client = Synnax.use();
const clientExists = client != null;
const addStatus = Status.useAggregator();
const isCreate = initialValues.key == null;

const { mutate, isPending } = useMutation({
mutationFn: async (persist: boolean) => {
mutationFn: async (persisted: boolean) => {
if (!methods.validate()) return;
const values = methods.value();
const { timeRange: tr, parent } = methods.value();
const { timeRange: tr, parent } = values;
const timeRange = new TimeRange(tr);
const name = values.name.trim();
const key = isCreate ? uuidv4() : (initialValues.key as string);
const persisted = persist || isRemoteEdit;
const key = initialValues.key ?? uuidv4();
const parentID = primitiveIsZero(parent)
? undefined
: new ontology.ID({ key: parent as string, type: "range" });
const otgID = new ontology.ID({ key, type: "range" });
if (persisted && client != null) {
if (persisted && clientExists) {
await client.ranges.create({ key, name, timeRange }, { parent: parentID });
await client.labels.label(otgID, values.labels, { replace: true });
}
Expand All @@ -198,7 +149,7 @@ const EditLayoutForm = ({
);

return (
<Align.Space className={CSS.B("range-edit-layout")} grow empty>
<Align.Space className={CSS.B("range-create-layout")} grow empty>
<Align.Space
className="console-form"
justify="center"
Expand Down Expand Up @@ -227,11 +178,7 @@ const EditLayoutForm = ({
</Form.Field>
</Align.Space>
<Align.Space direction="x">
<Form.Field<string>
path="parent"
visible={isCreate || isRemoteEdit}
padHelpText={false}
>
<Form.Field<string> path="parent" visible padHelpText={false}>
{({ onChange, ...p }) => (
<Ranger.SelectSingle
dropdownVariant="modal"
Expand Down Expand Up @@ -284,16 +231,26 @@ const EditLayoutForm = ({
<Nav.Bar.Start size="small">
<Triggers.Text shade={7} level="small" trigger={SAVE_TRIGGER} />
<Text.Text shade={7} level="small">
To Save
To Save to Synnax
</Text.Text>
</Nav.Bar.Start>
<Nav.Bar.End>
<Button.Button
onClick={() => mutate(true)}
variant={"outlined"}
onClick={() => mutate(false)}
disabled={isPending}
>
Save Locally
</Button.Button>
<Button.Button
onClick={() => mutate(true)}
disabled={!clientExists || isPending}
tooltip={clientExists ? "Save to Cluster" : "No Cluster Connected"}
tooltipLocation="bottom"
loading={isPending}
triggers={[SAVE_TRIGGER]}
>
Save
Save to Synnax
</Button.Button>
</Nav.Bar.End>
</Layout.BottomNavBar>
Expand Down
Loading
Loading