config
unknown
typescript
3 years ago
4.4 kB
8
Indexable
import random from "lodash/random";
import { Vue3Instance } from "vue/types/v3-component-public-instance";
import { createDraftSteps } from "./scenarios/base";
import { experimentsSteps } from "./scenarios/experiments";
import { tasksSteps } from "./scenarios/tasks";
export enum Tutorials {
"CreateDraft" = "CreateDraft",
"Experiments" = "Eperiments",
"Tasks" = "Tasks",
}
// @ts-ignore
export const startTutorial = async (tutorial: Tutorials, context: Vue3Instance) => {
let steps;
context.activeTour = tutorial;
context.tour = context?.$shepherd({
useModalOverlay: true,
keyboardNavigation: false,
exitOnEsc: true,
stepsContainer: document.querySelector(".tutorial__wrapper"),
modalContainer: document.querySelector(".tutorial__wrapper"),
confirmCancel: true,
confirmCancelMessage: "Are you sure you want to stop the tutorial?",
defaultStepOptions: {
classes: "shadow-md bg-purple-dark custom-step",
cancelIcon: {
enabled: true,
},
popperOptions: {
modifiers: [{ name: "offset", options: { offset: [0, 50] } }],
},
},
});
context.buttonStart = {
text: "Start tutorial",
classes: "v-btn v-btn--is-elevated v-btn--has-bg theme--light v-size--default primary",
action: await context.tour.next,
};
context.buttonNext = {
text: "Next",
classes: "v-btn v-btn--is-elevated v-btn--has-bg theme--light v-size--default primary",
action: context.tour.next,
};
context.buttonFinish = {
text: "Finish",
classes: "v-btn v-btn--is-elevated v-btn--has-bg theme--light v-size--default primary",
action: context.tour.complete,
};
context.buttonNextTutorial = {
text: "Next tutorial section",
classes: "v-btn v-btn--is-elevated v-btn--has-bg theme--light v-size--default primary",
action: () => {
context.tour.complete();
switch (context.activeTour) {
case "CreateDraft":
startTutorial(Tutorials.Experiments, context);
break;
case "Experiments":
startTutorial(Tutorials.Tasks, context);
break;
default:
break;
}
},
};
switch (tutorial) {
case Tutorials.CreateDraft:
steps = await createDraftSteps(context);
break;
case Tutorials.Experiments:
steps = await experimentsSteps(context);
context.tour.randomSeed = random();
break;
case Tutorials.Tasks:
steps = await tasksSteps(context);
break;
default:
break;
}
type Step = {
when?: { show?: () => void; cancel?: () => void; complete?: () => void };
};
context.tour.on("start", () => {
context.taskCreatorPersistent = true;
});
["cancel", "complete"].forEach((event) => {
context.tour.on(event, () => {
context.tour = undefined;
context.activeTour = undefined;
context.taskCreatorPersistent = false;
});
});
steps?.forEach((step: Step) => {
if (!step.when) {
step.when = {};
}
const showFunc = step.when.show;
step.when.show = () => {
addProgressToHeader(context.tour);
if (showFunc) {
showFunc();
}
};
});
context.tour.addSteps(steps);
context.tour.start();
};
// @ts-ignore
function addProgressToHeader(tour: Shepherd.Tour) {
const currentStepElement = tour.getCurrentStep().el;
const header = currentStepElement.querySelector(".shepherd-header");
const progress = document.createElement("span");
progress.style.setProperty("margin-right", "315px");
progress.innerText = `${tour.steps.indexOf(tour.getCurrentStep()) + 1}/${tour.steps.length}`;
header.insertBefore(progress, currentStepElement.querySelector(".shepherd-cancel-icon"));
}
export function findDrawflowNodeByName(regex: string | RegExp): Element | undefined {
return Array.from(document.querySelectorAll("div.drawflow-node").values()).find(
(e: Element) => e.textContent?.match(regex) ?? false
);
}
export function waitForElement(
selector: string,
callback: (el: Element) => void,
condition?: (el: Element) => boolean,
intervalMs = 500
) {
const interval = setInterval(() => {
try {
const element = document.querySelector(selector);
if (element && (!condition || condition(element))) {
callback(element);
clearInterval(interval);
return;
}
} catch {
clearInterval(interval);
}
}, intervalMs);
}
Editor is loading...