slice-machine-ui 1.19.2-dev-in-app-guide.2 → 1.19.2-dev-in-app-guide.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/pages/_app.tsx CHANGED
@@ -34,7 +34,7 @@ import { PersistGate } from "redux-persist/integration/react";
34
34
  import { ThemeProvider as ThemeUIThemeProvider, useThemeUI } from "theme-ui";
35
35
 
36
36
  import { AppLayout, AppLayoutContent } from "@components/AppLayout";
37
- import { InAppGuideDialog } from "@src/features/inAppGuide/InAppGuideDialog";
37
+ import { InAppGuideProvider } from "@src/features/inAppGuide/InAppGuideContext";
38
38
 
39
39
  import SliceMachineApp from "../components/App";
40
40
  import LoadingPage from "../components/LoadingPage";
@@ -123,48 +123,52 @@ function MyApp({
123
123
  <ThemeUIThemeProvider theme={theme}>
124
124
  <RemoveDarkMode>
125
125
  <ThemeProvider mode="light">
126
- <ErrorBoundary
127
- renderError={(error) => {
128
- console.error(error);
129
-
130
- return (
131
- <AppLayout>
132
- <AppLayoutContent>
133
- <Box alignItems="center" justifyContent="center">
134
- <DefaultErrorMessage
135
- title="Error"
136
- description="An error occurred while rendering the app."
137
- />
138
- </Box>
139
- </AppLayoutContent>
140
- </AppLayout>
141
- );
142
- }}
143
- >
144
- <TooltipProvider>
145
- {!smStore || !serverState ? (
146
- <LoadingPage />
147
- ) : (
148
- <Provider store={smStore.store}>
149
- <ConnectedRouter Router={Router}>
150
- <PersistGate loading={null} persistor={smStore.persistor}>
151
- <RouteChangeProvider>
152
- <Suspense fallback={<LoadingPage />}>
153
- <ComponentLayout>
154
- <Component {...pageProps} />
155
- </ComponentLayout>
156
- </Suspense>
157
- </RouteChangeProvider>
126
+ <TooltipProvider>
127
+ {!smStore || !serverState ? (
128
+ <LoadingPage />
129
+ ) : (
130
+ <Provider store={smStore.store}>
131
+ <ConnectedRouter Router={Router}>
132
+ <PersistGate loading={null} persistor={smStore.persistor}>
133
+ <ErrorBoundary
134
+ renderError={(error) => {
135
+ console.error(error);
136
+
137
+ return (
138
+ <AppLayout>
139
+ <AppLayoutContent>
140
+ <Box
141
+ alignItems="center"
142
+ justifyContent="center"
143
+ >
144
+ <DefaultErrorMessage
145
+ title="Error"
146
+ description="An error occurred while rendering the app."
147
+ />
148
+ </Box>
149
+ </AppLayoutContent>
150
+ </AppLayout>
151
+ );
152
+ }}
153
+ >
158
154
  <Suspense>
159
- <InAppGuideDialog />
155
+ <InAppGuideProvider>
156
+ <RouteChangeProvider>
157
+ <Suspense fallback={<LoadingPage />}>
158
+ <ComponentLayout>
159
+ <Component {...pageProps} />
160
+ </ComponentLayout>
161
+ </Suspense>
162
+ </RouteChangeProvider>
163
+ </InAppGuideProvider>
160
164
  </Suspense>
161
- </PersistGate>
162
- </ConnectedRouter>
163
- <ToastContainer />
164
- </Provider>
165
- )}
166
- </TooltipProvider>
167
- </ErrorBoundary>
165
+ </ErrorBoundary>
166
+ </PersistGate>
167
+ </ConnectedRouter>
168
+ <ToastContainer />
169
+ </Provider>
170
+ )}
171
+ </TooltipProvider>
168
172
  </ThemeProvider>
169
173
  </RemoveDarkMode>
170
174
  </ThemeUIThemeProvider>
@@ -0,0 +1,49 @@
1
+ import {
2
+ Dispatch,
3
+ FC,
4
+ PropsWithChildren,
5
+ SetStateAction,
6
+ createContext,
7
+ useContext,
8
+ } from "react";
9
+
10
+ import { usePersistedState } from "@src/hooks/usePersistedState";
11
+
12
+ import { InAppGuideDialog } from "./InAppGuideDialog";
13
+
14
+ type InAppGuideContextValue = {
15
+ isInAppGuideOpen: boolean;
16
+ setIsInAppGuideOpen: Dispatch<SetStateAction<boolean>>;
17
+ };
18
+
19
+ export const InAppGuideContext = createContext<
20
+ InAppGuideContextValue | undefined
21
+ >(undefined);
22
+
23
+ export const InAppGuideProvider: FC<PropsWithChildren> = (props) => {
24
+ const { children } = props;
25
+ const [isInAppGuideOpen, setIsInAppGuideOpen] = usePersistedState(
26
+ true,
27
+ "isInAppGuideOpen",
28
+ );
29
+
30
+ return (
31
+ <InAppGuideContext.Provider
32
+ value={{
33
+ isInAppGuideOpen,
34
+ setIsInAppGuideOpen,
35
+ }}
36
+ >
37
+ {children}
38
+ <InAppGuideDialog />
39
+ </InAppGuideContext.Provider>
40
+ );
41
+ };
42
+
43
+ export const useInAppGuide = () => {
44
+ const context = useContext(InAppGuideContext);
45
+ if (context === undefined) {
46
+ throw new Error("useInAppGuide must be used within a InAppGuideProvider");
47
+ }
48
+ return context;
49
+ };
@@ -14,21 +14,30 @@ import {
14
14
  import { Counter } from "@src/components/Counter";
15
15
  import { FlowerBackgroundIcon } from "@src/icons/FlowerBackgroundIcon";
16
16
  import { HelpIcon } from "@src/icons/HelpIcon";
17
- import { usePersistedState } from "@src/hooks/usePersistedState";
18
17
  import { useIsEmptyProject } from "@src/hooks/useIsEmptyProject";
19
18
 
20
- import { IN_APP_GUIDE_CONTENT } from "./inAppGuideContent";
19
+ import { useInAppGuideContent } from "./inAppGuideContent";
20
+ import { useInAppGuide } from "./InAppGuideContext";
21
21
 
22
22
  export const InAppGuideDialog: FC = () => {
23
23
  const isEmptyProject = useIsEmptyProject();
24
- const [isInAppGuideOpen, setIsInAppGuideOpen] = usePersistedState(
25
- true,
26
- "isInAppGuideOpen",
27
- );
24
+ const { isInAppGuideOpen, setIsInAppGuideOpen } = useInAppGuide();
25
+ const inAppGuideContent = useInAppGuideContent();
26
+
27
+ // TODO: Use new IconButton component from editor-ui
28
+ //
29
+ // It should be used like that:
30
+ // <IconButton
31
+ // color="purple"
32
+ // radius="full"
33
+ // renderIcon={() => <HelpIcon />}
34
+ // onClick={() => {
35
+ // setIsInAppGuideOpen(!isInAppGuideOpen);
36
+ // }}
37
+ // />
28
38
 
29
- // TODO: Use IconButton from @prismicio/editor-ui
30
39
  const trigger =
31
- isInAppGuideOpen === false && isEmptyProject === false ? (
40
+ isEmptyProject === false ? (
32
41
  <Box position="fixed" right={16} bottom={16}>
33
42
  <button
34
43
  style={{
@@ -63,13 +72,25 @@ export const InAppGuideDialog: FC = () => {
63
72
  position="bottomRight"
64
73
  size={{
65
74
  width: 360,
66
- height: 440,
75
+ height: 456,
67
76
  }}
68
77
  >
69
- <DialogHeader title={IN_APP_GUIDE_CONTENT.title} />
78
+ <DialogHeader title={inAppGuideContent.title} />
70
79
  <DialogContent>
71
80
  <ScrollArea>
72
- {IN_APP_GUIDE_CONTENT.steps.map((content, index) => (
81
+ <Box
82
+ flexDirection="column"
83
+ padding={{ inline: 16, block: 8 }}
84
+ gap={8}
85
+ >
86
+ <Text>{inAppGuideContent.description}</Text>
87
+ </Box>
88
+
89
+ <Box>
90
+ <Separator />
91
+ </Box>
92
+
93
+ {inAppGuideContent.steps.map((content, index) => (
73
94
  <Box key={index} flexDirection="column">
74
95
  <Box flexDirection="column" padding={16} gap={8}>
75
96
  <Box alignItems="center" gap={8}>
@@ -95,12 +116,8 @@ export const InAppGuideDialog: FC = () => {
95
116
  ))}
96
117
 
97
118
  <Box flexDirection="column" padding={16} gap={4}>
98
- <Text variant="bold">{IN_APP_GUIDE_CONTENT.successTitle}</Text>
99
- <Box flexDirection="column">
100
- {IN_APP_GUIDE_CONTENT.successSteps.map((content, index) => (
101
- <Text key={index}>• {content}</Text>
102
- ))}
103
- </Box>
119
+ <Text variant="bold">{inAppGuideContent.successTitle}</Text>
120
+ <Text>{inAppGuideContent.successDescription}</Text>
104
121
  </Box>
105
122
  </ScrollArea>
106
123
  </DialogContent>
@@ -1,68 +1,67 @@
1
- import { TextLink } from "@prismicio/editor-ui";
1
+ import { TextLink, Text } from "@prismicio/editor-ui";
2
2
 
3
- export const IN_APP_GUIDE_CONTENT = {
4
- title: "Build your first page in 5 minutes",
5
- steps: [
6
- {
7
- title: "Add slice to your page",
8
- videoUrl:
9
- "https://images.prismic.io/page-builder-assets/8f5df837-d8c2-4aed-832c-dec21d3915d0_New+Recording+Jul+18+2023+0350+PM.mp4",
10
- description:
11
- "Try one of our templates to get started after the creation of your first page",
12
- },
13
- {
14
- title: "Code your page",
15
- videoUrl:
16
- "https://images.prismic.io/page-builder-assets/8f5df837-d8c2-4aed-832c-dec21d3915d0_New+Recording+Jul+18+2023+0350+PM.mp4",
17
- description:
18
- "Slice Machine provides code snippets. Copy-paste them into your page component to render your page.",
19
- },
20
- {
21
- title: "Push models to the Page Builder",
22
- videoUrl:
23
- "https://images.prismic.io/page-builder-assets/8f5df837-d8c2-4aed-832c-dec21d3915d0_New+Recording+Jul+18+2023+0350+PM.mp4",
24
- description:
25
- "You have just created some models, but you can’t use them yet. First, you must push them to the Page Builder. The Page Builder is where you create content. Go head — push your models.",
26
- },
27
- {
28
- title: "Create your first page",
29
- videoUrl:
30
- "https://images.prismic.io/page-builder-assets/8f5df837-d8c2-4aed-832c-dec21d3915d0_New+Recording+Jul+18+2023+0350+PM.mp4",
31
- description: (
32
- <>
33
- In your{" "}
34
- <TextLink href="TODO" underline>
35
- Page Builder
36
- </TextLink>
37
- , create your first page. Add slices to the page to create content.
38
- Then save and publish and come back here.
39
- </>
40
- ),
41
- },
42
- {
43
- title: "Render your page",
44
- videoUrl:
45
- "https://images.prismic.io/page-builder-assets/8f5df837-d8c2-4aed-832c-dec21d3915d0_New+Recording+Jul+18+2023+0350+PM.mp4",
46
- description: (
47
- <>
48
- Run your project on{" "}
49
- <TextLink href="TODO" underline>
50
- localhost
51
- </TextLink>{" "}
52
- to see your first page.
53
- </>
54
- ),
55
- },
56
- ],
57
- successTitle: "You have made your first page!",
58
- successSteps: [
59
- "Edit, and style your slices",
60
- "Create more pages in the Page Builder",
61
- <>
62
- Learn how to{" "}
63
- <TextLink href="TODO" underline>
64
- manage your routes
65
- </TextLink>
66
- </>,
67
- ],
68
- };
3
+ import { useRepositoryInformation } from "@src/hooks/useRepositoryInformation";
4
+
5
+ export function useInAppGuideContent() {
6
+ const { repositoryUrl } = useRepositoryInformation();
7
+
8
+ return {
9
+ title: "Build a page in 5 minutes",
10
+ description:
11
+ "Great, now that you have a page type, let's make it a live page!",
12
+ steps: [
13
+ {
14
+ title: "Add slices to your page type",
15
+ videoUrl:
16
+ "https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/ADD_SLICE.mp4",
17
+ description: "Use slice templates and add them to your page type.",
18
+ },
19
+ {
20
+ title: "Code your page",
21
+ videoUrl:
22
+ "https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/CODE_SNIP.mp4",
23
+ description:
24
+ "If you don't already have a page component, copy-paste the page snippets provided in your page type to create one.",
25
+ },
26
+ {
27
+ title: "Push to your Page Builder",
28
+ videoUrl:
29
+ "https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/PUSH.mp4",
30
+ description:
31
+ "You have just created some models, but you can't use them yet. First, you must push them to the Page Builder. The Page Builder is where you create content. Go head — push your models.",
32
+ },
33
+ {
34
+ title: "Create content",
35
+ videoUrl:
36
+ "https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/WRITE.mp4",
37
+ description: (
38
+ <>
39
+ Open your{" "}
40
+ <TextLink href={repositoryUrl} underline>
41
+ Page Builder
42
+ </TextLink>
43
+ , create a page, add slices, save and publish. Then, come back here.
44
+ </>
45
+ ),
46
+ },
47
+ {
48
+ title: "Render your page",
49
+ videoUrl:
50
+ "https://res.cloudinary.com/dmtf1daqp/video/upload/v1700213517/IN-APP-GUIDE-SM/PREVIEW.mp4",
51
+ description: (
52
+ <>
53
+ To render the page, run your project in your terminal and open
54
+ localhost to the page UID.{" "}
55
+ <Text variant="italic" component="span" sx={{}}>
56
+ Example:
57
+ </Text>{" "}
58
+ localhost:3000/my_page_uid
59
+ </>
60
+ ),
61
+ },
62
+ ],
63
+ successTitle: "Next",
64
+ successDescription:
65
+ "Create more slices and then go back to the Page Builder to build out your website.",
66
+ };
67
+ }
@@ -0,0 +1,24 @@
1
+ import { useSelector } from "react-redux";
2
+
3
+ import { SliceMachineStoreType } from "@src/redux/type";
4
+ import { getApiEndpoint, getRepoName } from "@src/modules/environment";
5
+
6
+ // TODO: This hook should be extracted to a new manager endpoint
7
+ export function useRepositoryInformation() {
8
+ const { repositoryName, apiEndpoint } = useSelector(
9
+ (store: SliceMachineStoreType) => ({
10
+ repositoryName: getRepoName(store),
11
+ apiEndpoint: getApiEndpoint(store),
12
+ }),
13
+ );
14
+ const repositoryDomain = new URL(apiEndpoint).hostname.replace(".cdn", "");
15
+ const repositoryUrl = apiEndpoint
16
+ .replace(".cdn.", ".")
17
+ .replace("/api/v2", "");
18
+
19
+ return {
20
+ repositoryName,
21
+ repositoryDomain,
22
+ repositoryUrl,
23
+ };
24
+ }