kopia lustrzana https://github.com/bugout-dev/moonstream
Merge branch 'main' into extend-subscriptions
commit
1f36d16585
|
@ -1,7 +1,9 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
|
||||||
|
from typing import Optional, Dict, Any
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
import uuid
|
||||||
|
|
||||||
import boto3 # type: ignore
|
import boto3 # type: ignore
|
||||||
from moonstreamdb.models import (
|
from moonstreamdb.models import (
|
||||||
|
@ -14,6 +16,12 @@ from sqlalchemy.orm import Session
|
||||||
from . import data
|
from . import data
|
||||||
from .reporter import reporter
|
from .reporter import reporter
|
||||||
from .settings import ETHERSCAN_SMARTCONTRACTS_BUCKET
|
from .settings import ETHERSCAN_SMARTCONTRACTS_BUCKET
|
||||||
|
from bugout.data import BugoutResource
|
||||||
|
from .settings import (
|
||||||
|
MOONSTREAM_APPLICATION_ID,
|
||||||
|
bugout_client as bc,
|
||||||
|
BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
ETHERSCAN_SMARTCONTRACT_LABEL_NAME = "etherscan_smartcontract"
|
ETHERSCAN_SMARTCONTRACT_LABEL_NAME = "etherscan_smartcontract"
|
||||||
|
@ -144,3 +152,21 @@ def get_address_labels(
|
||||||
)
|
)
|
||||||
|
|
||||||
return addresses_response
|
return addresses_response
|
||||||
|
|
||||||
|
|
||||||
|
def create_onboarding_resource(
|
||||||
|
token: uuid.UUID,
|
||||||
|
resource_data: Dict[str, Any] = {
|
||||||
|
"type": data.USER_ONBOARDING_STATE,
|
||||||
|
"steps": {"welcome": 0, "subscriptions": 0, "stream": 0,},
|
||||||
|
"is_complete": False,
|
||||||
|
},
|
||||||
|
) -> BugoutResource:
|
||||||
|
|
||||||
|
resource = bc.create_resource(
|
||||||
|
token=token,
|
||||||
|
application_id=MOONSTREAM_APPLICATION_ID,
|
||||||
|
resource_data=resource_data,
|
||||||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
|
)
|
||||||
|
return resource
|
||||||
|
|
|
@ -5,6 +5,8 @@ from typing import List, Optional, Dict, Any
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
USER_ONBOARDING_STATE = "onboarding_state"
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionTypeResourceData(BaseModel):
|
class SubscriptionTypeResourceData(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
|
@ -196,3 +198,8 @@ class AddressLabelsResponse(BaseModel):
|
||||||
|
|
||||||
class AddressListLabelsResponse(BaseModel):
|
class AddressListLabelsResponse(BaseModel):
|
||||||
addresses: List[AddressLabelsResponse] = Field(default_factory=list)
|
addresses: List[AddressLabelsResponse] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
class OnboardingState(BaseModel):
|
||||||
|
is_complete: bool
|
||||||
|
steps: Dict[str, int]
|
||||||
|
|
|
@ -5,20 +5,30 @@ import logging
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from bugout.data import BugoutToken, BugoutUser
|
from bugout.data import BugoutToken, BugoutUser, BugoutResource
|
||||||
from bugout.exceptions import BugoutResponseException
|
from bugout.exceptions import BugoutResponseException
|
||||||
from fastapi import FastAPI, Form, Request
|
|
||||||
|
from fastapi import (
|
||||||
|
Body,
|
||||||
|
FastAPI,
|
||||||
|
Form,
|
||||||
|
Request,
|
||||||
|
)
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
|
from .. import data
|
||||||
from ..middleware import BroodAuthMiddleware, MoonstreamHTTPException
|
from ..middleware import BroodAuthMiddleware, MoonstreamHTTPException
|
||||||
|
|
||||||
from ..settings import (
|
from ..settings import (
|
||||||
MOONSTREAM_APPLICATION_ID,
|
MOONSTREAM_APPLICATION_ID,
|
||||||
DOCS_TARGET_PATH,
|
DOCS_TARGET_PATH,
|
||||||
ORIGINS,
|
ORIGINS,
|
||||||
DOCS_PATHS,
|
DOCS_PATHS,
|
||||||
bugout_client as bc,
|
bugout_client as bc,
|
||||||
|
BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
)
|
)
|
||||||
from ..version import MOONSTREAM_VERSION
|
from ..version import MOONSTREAM_VERSION
|
||||||
|
from ..actions import create_onboarding_resource
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -166,3 +176,121 @@ async def logout_handler(request: Request) -> uuid.UUID:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
raise MoonstreamHTTPException(status_code=500, internal_error=e)
|
||||||
return token_id
|
return token_id
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/onboarding", tags=["users"], response_model=data.OnboardingState)
|
||||||
|
async def set_onboarding_state(
|
||||||
|
request: Request, onboarding_data: data.OnboardingState = Body(...),
|
||||||
|
) -> data.OnboardingState:
|
||||||
|
|
||||||
|
token = request.state.token
|
||||||
|
try:
|
||||||
|
response = bc.list_resources(
|
||||||
|
token=token,
|
||||||
|
params={"type": data.USER_ONBOARDING_STATE},
|
||||||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
|
)
|
||||||
|
resource_data = {"type": data.USER_ONBOARDING_STATE, **onboarding_data.dict()}
|
||||||
|
if response.resources:
|
||||||
|
resource = bc.update_resource(
|
||||||
|
token=token,
|
||||||
|
resource_id=str(response.resources[0].id),
|
||||||
|
resource_data={"update": resource_data, "drop_keys": []},
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
resource = create_onboarding_resource(
|
||||||
|
token=token, resource_data=resource_data
|
||||||
|
)
|
||||||
|
|
||||||
|
except BugoutResponseException as e:
|
||||||
|
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||||||
|
except Exception as e:
|
||||||
|
raise MoonstreamHTTPException(status_code=500)
|
||||||
|
|
||||||
|
if (
|
||||||
|
resource.resource_data.get("is_complete") is None
|
||||||
|
or resource.resource_data.get("steps") is None
|
||||||
|
):
|
||||||
|
logger.error(
|
||||||
|
f"Resources did not return correct onboarding object. Resource id:{resource.id}"
|
||||||
|
)
|
||||||
|
raise MoonstreamHTTPException(status_code=500)
|
||||||
|
|
||||||
|
result = data.OnboardingState(
|
||||||
|
is_complete=resource.resource_data.get("is_complete", False),
|
||||||
|
steps=resource.resource_data.get("steps", {}),
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/onboarding", tags=["users"], response_model=data.OnboardingState)
|
||||||
|
async def get_onboarding_state(request: Request) -> data.OnboardingState:
|
||||||
|
token = request.state.token
|
||||||
|
try:
|
||||||
|
response = bc.list_resources(
|
||||||
|
token=token,
|
||||||
|
params={"type": data.USER_ONBOARDING_STATE},
|
||||||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.resources:
|
||||||
|
resource = response.resources[0]
|
||||||
|
else:
|
||||||
|
resource = create_onboarding_resource(token=token)
|
||||||
|
except BugoutResponseException as e:
|
||||||
|
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||||||
|
except Exception as e:
|
||||||
|
|
||||||
|
raise MoonstreamHTTPException(status_code=500)
|
||||||
|
|
||||||
|
if (
|
||||||
|
resource.resource_data.get("is_complete") is None
|
||||||
|
or resource.resource_data.get("steps") is None
|
||||||
|
):
|
||||||
|
logger.error(
|
||||||
|
f"Resources did not return correct onboarding object. Resource id:{resource.id}"
|
||||||
|
)
|
||||||
|
raise MoonstreamHTTPException(status_code=500)
|
||||||
|
result = data.OnboardingState(
|
||||||
|
is_complete=resource.resource_data.get("is_complete", False),
|
||||||
|
steps=resource.resource_data.get("steps", {}),
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@app.delete("/onboarding", tags=["users"], response_model=data.OnboardingState)
|
||||||
|
async def delete_onboarding_state(request: Request) -> data.OnboardingState:
|
||||||
|
token = request.state.token
|
||||||
|
try:
|
||||||
|
response = bc.list_resources(
|
||||||
|
token=token,
|
||||||
|
params={"type": data.USER_ONBOARDING_STATE},
|
||||||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
|
)
|
||||||
|
if not response.resources:
|
||||||
|
raise MoonstreamHTTPException(status_code=404, detail="not found")
|
||||||
|
if response.resources:
|
||||||
|
resource: BugoutResource = bc.delete_resource(
|
||||||
|
token=token,
|
||||||
|
resource_id=response.resources[0].id,
|
||||||
|
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
|
||||||
|
)
|
||||||
|
|
||||||
|
except BugoutResponseException as e:
|
||||||
|
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
|
||||||
|
except Exception as e:
|
||||||
|
raise MoonstreamHTTPException(status_code=500)
|
||||||
|
|
||||||
|
if (
|
||||||
|
resource.resource_data.get("is_complete") is None
|
||||||
|
or resource.resource_data.get("steps") is None
|
||||||
|
):
|
||||||
|
logger.error(
|
||||||
|
f"Resources did not return correct onboarding object. Resource id:{resource.id}"
|
||||||
|
)
|
||||||
|
raise MoonstreamHTTPException(status_code=500)
|
||||||
|
result = data.OnboardingState(
|
||||||
|
is_complete=resource.resource_data.get("is_complete", False),
|
||||||
|
steps=resource.resource_data.get("steps", {}),
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
import codecs
|
||||||
|
import csv
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
|
||||||
from typing import Any, List, Optional, Dict
|
from typing import Any, List, Optional, Dict
|
||||||
from dataclasses import dataclass
|
|
||||||
import csv
|
|
||||||
import codecs
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
|
|
||||||
import boto3 # type: ignore
|
import boto3 # type: ignore
|
||||||
from moonstreamdb.db import yield_db_session_ctx
|
from moonstreamdb.db import yield_db_session_ctx
|
||||||
from moonstreamdb.models import EthereumAddress, EthereumLabel
|
from moonstreamdb.models import EthereumAddress, EthereumLabel
|
||||||
import requests
|
import requests
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy.sql.expression import text
|
|
||||||
|
|
||||||
from .version import MOONCRAWL_VERSION
|
from .version import MOONCRAWL_VERSION
|
||||||
from .settings import MOONSTREAM_ETHERSCAN_TOKEN
|
from .settings import MOONSTREAM_ETHERSCAN_TOKEN
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
if MOONSTREAM_ETHERSCAN_TOKEN is None:
|
if MOONSTREAM_ETHERSCAN_TOKEN is None:
|
||||||
raise Exception("MOONSTREAM_ETHERSCAN_TOKEN environment variable must be set")
|
raise Exception("MOONSTREAM_ETHERSCAN_TOKEN environment variable must be set")
|
||||||
|
|
||||||
|
@ -66,21 +68,16 @@ def get_address_id(db_session: Session, contract_address: str) -> int:
|
||||||
if id is not None:
|
if id is not None:
|
||||||
return id[0]
|
return id[0]
|
||||||
|
|
||||||
latest_address_id = (
|
|
||||||
db_session.query(EthereumAddress.id).order_by(text("id desc")).limit(1).one()
|
|
||||||
)[0]
|
|
||||||
|
|
||||||
id = latest_address_id + 1
|
|
||||||
smart_contract = EthereumAddress(
|
smart_contract = EthereumAddress(
|
||||||
id=id,
|
|
||||||
address=contract_address,
|
address=contract_address,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
db_session.add(smart_contract)
|
db_session.add(smart_contract)
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
except:
|
return smart_contract.id
|
||||||
|
except Exception as e:
|
||||||
db_session.rollback()
|
db_session.rollback()
|
||||||
return id
|
raise e
|
||||||
|
|
||||||
|
|
||||||
def crawl_step(db_session: Session, contract: VerifiedSmartContract, crawl_url: str):
|
def crawl_step(db_session: Session, contract: VerifiedSmartContract, crawl_url: str):
|
||||||
|
@ -112,8 +109,8 @@ def crawl_step(db_session: Session, contract: VerifiedSmartContract, crawl_url:
|
||||||
object_key = f"/etherscan/v1/{contract.address}.json"
|
object_key = f"/etherscan/v1/{contract.address}.json"
|
||||||
push_to_bucket(contract_info, object_key)
|
push_to_bucket(contract_info, object_key)
|
||||||
|
|
||||||
|
try:
|
||||||
eth_address_id = get_address_id(db_session, contract.address)
|
eth_address_id = get_address_id(db_session, contract.address)
|
||||||
|
|
||||||
eth_label = EthereumLabel(
|
eth_label = EthereumLabel(
|
||||||
label=ETHERSCAN_SMARTCONTRACTS_LABEL_NAME,
|
label=ETHERSCAN_SMARTCONTRACTS_LABEL_NAME,
|
||||||
address_id=eth_address_id,
|
address_id=eth_address_id,
|
||||||
|
@ -126,8 +123,13 @@ def crawl_step(db_session: Session, contract: VerifiedSmartContract, crawl_url:
|
||||||
try:
|
try:
|
||||||
db_session.add(eth_label)
|
db_session.add(eth_label)
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
except:
|
except Exception as e:
|
||||||
db_session.rollback()
|
db_session.rollback()
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
f"Failed to add addresss label ${contract.address} to database\n{str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def crawl(
|
def crawl(
|
||||||
|
|
|
@ -70,7 +70,7 @@ const Welcome = () => {
|
||||||
ui.setOnboardingStep(ui.onboardingStep + 1);
|
ui.setOnboardingStep(ui.onboardingStep + 1);
|
||||||
scrollRef?.current?.scrollIntoView();
|
scrollRef?.current?.scrollIntoView();
|
||||||
} else {
|
} else {
|
||||||
ui.setisOnboardingComplete(true);
|
ui.setOnboardingComplete(true);
|
||||||
router.push("/stream");
|
router.push("/stream");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,12 +115,6 @@ const AppNavbar = () => {
|
||||||
</RouteButton>
|
</RouteButton>
|
||||||
))}
|
))}
|
||||||
{USER_NAV_PATHES.map((item, idx) => {
|
{USER_NAV_PATHES.map((item, idx) => {
|
||||||
console.log(
|
|
||||||
"item.path:",
|
|
||||||
item.path,
|
|
||||||
"pathname:",
|
|
||||||
router.nextRouter.pathname
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<RouteButton
|
<RouteButton
|
||||||
key={`${idx}-${item.title}-navlink`}
|
key={`${idx}-${item.title}-navlink`}
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
import React, { useState, useContext, useEffect } from "react";
|
import React, { useState, useContext, useEffect, useCallback } from "react";
|
||||||
import { useBreakpointValue } from "@chakra-ui/react";
|
import { useBreakpointValue } from "@chakra-ui/react";
|
||||||
import { useStorage, useQuery, useRouter } from "../../hooks";
|
import { useStorage, useQuery, useRouter } from "../../hooks";
|
||||||
import UIContext from "./context";
|
import UIContext from "./context";
|
||||||
import UserContext from "../UserProvider/context";
|
import UserContext from "../UserProvider/context";
|
||||||
import ModalContext from "../ModalProvider/context";
|
import ModalContext from "../ModalProvider/context";
|
||||||
import { v4 as uuid4 } from "uuid";
|
import { v4 as uuid4 } from "uuid";
|
||||||
|
import { PreferencesService } from "../../services";
|
||||||
|
|
||||||
|
const onboardingSteps = [
|
||||||
|
{
|
||||||
|
step: "welcome",
|
||||||
|
description: "Basics of how Moonstream works",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: "subscriptions",
|
||||||
|
description: "Learn how to subscribe to blockchain events",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: "stream",
|
||||||
|
description: "Learn how to use your Moonstream to analyze blah blah blah",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const UIProvider = ({ children }) => {
|
const UIProvider = ({ children }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -53,14 +69,6 @@ const UIProvider = ({ children }) => {
|
||||||
}
|
}
|
||||||
}, [isAppView, user, isLoggingOut]);
|
}, [isAppView, user, isLoggingOut]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isInit && router.nextRouter.isReady) {
|
|
||||||
setAppReady(true);
|
|
||||||
} else {
|
|
||||||
setAppReady(false);
|
|
||||||
}
|
|
||||||
}, [isInit, router]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user && user.username) {
|
if (user && user.username) {
|
||||||
setLoggedIn(true);
|
setLoggedIn(true);
|
||||||
|
@ -155,90 +163,109 @@ const UIProvider = ({ children }) => {
|
||||||
|
|
||||||
// *********** Onboarding state **********************
|
// *********** Onboarding state **********************
|
||||||
|
|
||||||
const onboardingSteps = [
|
const [onboardingState, setOnboardingState] = useState(false);
|
||||||
{
|
const [onboardingStep, setOnboardingStep] = useState();
|
||||||
step: "welcome",
|
const [onboardingStateInit, setOnboardingStateInit] = useState(false);
|
||||||
description: "Basics of how Moonstream works",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
step: "subscriptions",
|
|
||||||
description: "Learn how to subscribe to blockchain events",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
step: "stream",
|
|
||||||
description: "Learn how to use your Moonstream to analyze blah blah blah",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [onboardingState, setOnboardingState] = useStorage(
|
const setOnboardingComplete = useCallback(
|
||||||
window.localStorage,
|
(newState) => {
|
||||||
"onboardingState",
|
setOnboardingState({ ...onboardingState, is_complete: newState });
|
||||||
{
|
},
|
||||||
welcome: 0,
|
[onboardingState]
|
||||||
subscriptions: 0,
|
|
||||||
stream: 0,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const [onboardingStep, setOnboardingStep] = useState(() => {
|
|
||||||
//First find onboarding step that was viewed once (resume where left)
|
|
||||||
// If none - find step that was never viewed
|
|
||||||
// if none - set onboarding to zero
|
|
||||||
let step = onboardingSteps.findIndex(
|
|
||||||
(event) => onboardingState[event.step] === 1
|
|
||||||
);
|
|
||||||
step =
|
|
||||||
step === -1
|
|
||||||
? onboardingSteps.findIndex(
|
|
||||||
(event) => onboardingState[event.step] === 0
|
|
||||||
)
|
|
||||||
: step;
|
|
||||||
if (step === -1 && isOnboardingComplete) return 0;
|
|
||||||
else if (step === -1 && !isOnboardingComplete) return 0;
|
|
||||||
else return step;
|
|
||||||
});
|
|
||||||
|
|
||||||
const [isOnboardingComplete, setisOnboardingComplete] = useStorage(
|
|
||||||
window.localStorage,
|
|
||||||
"isOnboardingComplete",
|
|
||||||
isLoggedIn ? true : false
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoggedIn && !isOnboardingComplete) {
|
//If onboarding state not exists - fetch it from backend
|
||||||
|
//If it exists but init is not set - set init true
|
||||||
|
//If it exists and is init -> post update to backend
|
||||||
|
if (!onboardingState && user) {
|
||||||
|
const currentOnboardingState = async () =>
|
||||||
|
PreferencesService.getOnboardingState().then((response) => {
|
||||||
|
return response.data;
|
||||||
|
});
|
||||||
|
|
||||||
|
currentOnboardingState().then((response) => {
|
||||||
|
setOnboardingState(response);
|
||||||
|
});
|
||||||
|
} else if (user && onboardingState && !onboardingStateInit) {
|
||||||
|
setOnboardingStateInit(true);
|
||||||
|
} else if (onboardingStateInit) {
|
||||||
|
PreferencesService.setOnboardingState(onboardingState);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [onboardingState, user]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//This will set step after state is fetched from backend
|
||||||
|
if (!Number.isInteger(onboardingStep) && onboardingState) {
|
||||||
|
const step = onboardingSteps.findIndex(
|
||||||
|
(event) => onboardingState[event.step] === 0
|
||||||
|
);
|
||||||
|
if (step === -1 && onboardingState["is_complete"])
|
||||||
|
setOnboardingStep(onboardingSteps.length - 1);
|
||||||
|
else if (step === -1 && !onboardingState["is_complete"])
|
||||||
|
return setOnboardingStep(0);
|
||||||
|
else setOnboardingStep(step);
|
||||||
|
}
|
||||||
|
}, [onboardingState, onboardingStep]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//redirect to welcome page if yet not completed onboarding
|
||||||
|
if (
|
||||||
|
isLoggedIn &&
|
||||||
|
isAppReady &&
|
||||||
|
onboardingState &&
|
||||||
|
!onboardingState?.is_complete
|
||||||
|
) {
|
||||||
router.replace("/welcome");
|
router.replace("/welcome");
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [isLoggedIn, isOnboardingComplete]);
|
}, [isLoggedIn, onboardingState?.is_complete, isAppReady]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
//This will set up onboarding complete once user finishes each view at least once
|
||||||
|
if (onboardingState?.steps && user && isAppReady) {
|
||||||
if (
|
if (
|
||||||
onboardingSteps.findIndex(
|
onboardingSteps.findIndex(
|
||||||
(event) => onboardingState[event.step] === 0
|
(event) => onboardingState.steps[event.step] === 0
|
||||||
) === -1
|
) === -1
|
||||||
) {
|
) {
|
||||||
setisOnboardingComplete(true);
|
!onboardingState.is_complete && setOnboardingComplete(true);
|
||||||
}
|
}
|
||||||
//eslint-disable-next-line
|
}
|
||||||
}, [onboardingState]);
|
}, [onboardingState, user, isAppReady, setOnboardingComplete]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (router.nextRouter.pathname === "/welcome") {
|
//This will update onboardingState when step changes
|
||||||
const newOnboardingState = {
|
if (
|
||||||
|
router.nextRouter.pathname === "/welcome" &&
|
||||||
|
isAppReady &&
|
||||||
|
user &&
|
||||||
|
Number.isInteger(onboardingStep) &&
|
||||||
|
onboardingState
|
||||||
|
) {
|
||||||
|
setOnboardingState({
|
||||||
...onboardingState,
|
...onboardingState,
|
||||||
|
steps: {
|
||||||
|
...onboardingState.steps,
|
||||||
[`${onboardingSteps[onboardingStep].step}`]:
|
[`${onboardingSteps[onboardingStep].step}`]:
|
||||||
onboardingState[onboardingSteps[onboardingStep].step] + 1,
|
onboardingState.steps[onboardingSteps[onboardingStep].step] + 1,
|
||||||
};
|
},
|
||||||
|
});
|
||||||
setOnboardingState(newOnboardingState);
|
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [onboardingStep, router.nextRouter.pathname]);
|
}, [onboardingStep, router.nextRouter.pathname, user, isAppReady]);
|
||||||
|
|
||||||
// const ONBOARDING_STEP_NUM = steps.length;
|
|
||||||
|
|
||||||
// ********************************************************
|
// ********************************************************
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isInit && router.nextRouter.isReady && onboardingState) {
|
||||||
|
setAppReady(true);
|
||||||
|
} else {
|
||||||
|
setAppReady(false);
|
||||||
|
}
|
||||||
|
}, [isInit, router, onboardingState]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UIContext.Provider
|
<UIContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
@ -268,8 +295,7 @@ const UIProvider = ({ children }) => {
|
||||||
isEntryDetailView,
|
isEntryDetailView,
|
||||||
onboardingStep,
|
onboardingStep,
|
||||||
setOnboardingStep,
|
setOnboardingStep,
|
||||||
isOnboardingComplete,
|
setOnboardingComplete,
|
||||||
setisOnboardingComplete,
|
|
||||||
onboardingSteps,
|
onboardingSteps,
|
||||||
setOnboardingState,
|
setOnboardingState,
|
||||||
onboardingState,
|
onboardingState,
|
||||||
|
|
|
@ -1,23 +1,18 @@
|
||||||
import { http } from "../utils";
|
import { http } from "../utils";
|
||||||
|
|
||||||
const API = process.env.NEXT_PUBLIC_SIMIOTICS_JOURNALS_URL;
|
const API_URL = process.env.NEXT_PUBLIC_MOONSTREAM_API_URL;
|
||||||
const PREFERENCES_API = `${API}/preferences`;
|
export const PREFERENCES_URL = `${API_URL}/users`;
|
||||||
|
|
||||||
export const getDefaultJournal = () =>
|
export const getOnboardingState = () =>
|
||||||
http({
|
http({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: `${PREFERENCES_API}/default_journal`,
|
url: `${PREFERENCES_URL}/onboarding`,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setDefaultJournal = (journalId) =>
|
export const setOnboardingState = (data) => {
|
||||||
http({
|
return http({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: `${PREFERENCES_API}/default_journal`,
|
url: `${PREFERENCES_URL}/onboarding`,
|
||||||
data: { id: journalId },
|
data,
|
||||||
});
|
|
||||||
|
|
||||||
export const unsetDefaultJournal = () =>
|
|
||||||
http({
|
|
||||||
method: "DELETE",
|
|
||||||
url: `${PREFERENCES_API}/default_journal`,
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
Ładowanie…
Reference in New Issue