Commit e6e09d49 authored by John Chilton's avatar John Chilton
Browse files

Add tour requiements.

Allow tours to annotate they need a logged in user, admin user, or new history.
parent 8aceb264
Loading
Loading
Loading
Loading
+73 −9
Original line number Diff line number Diff line
<template>
    <CurrentUser v-slot="{ user }" class="d-flex flex-column">
        <UserHistories v-if="user" v-slot="{ currentHistory, handlers, historiesLoading }" :user="user">
            <div v-if="historiesLoading">computing tour requirements...</div>
            <b-modal
                id="tour-requirement-unment"
                v-model="showRequirementDialog"
                static
                ok-only
                hide-header
                v-else-if="loginRequired(user)">
                <b-alert show variant="danger"> You must login to Galaxy to use this tour. </b-alert>
            </b-modal>
            <b-modal
                id="tour-requirement-unment"
                v-model="showRequirementDialog"
                static
                ok-only
                hide-header
                v-else-if="adminRequired(user)">
                <b-alert show variant="danger"> You must be an admin user to use this tour. </b-alert>
            </b-modal>
            <b-modal
                id="tour-requirement-unment"
                v-model="showRequirementDialog"
                static
                ok-only
                hide-header
                v-else-if="newHistoryRequired(currentHistory, handlers)">
                <b-alert show variant="danger">
                    This tour is designed to run on a new history, please create a new history before running it.
                    <a @click.prevent="handlers.createNewHistory()">Click here</a> to create a new history.
                </b-alert>
            </b-modal>
            <TourStep
        v-if="currentStep"
                v-else-if="currentStep"
                :key="currentIndex"
                :step="currentStep"
                :is-playing="isPlaying"
@@ -8,10 +41,14 @@
                @next="next"
                @end="end"
                @play="play" />
        </UserHistories>
    </CurrentUser>
</template>

<script>
import TourStep from "./TourStep";
import CurrentUser from "components/providers/CurrentUser";
import UserHistories from "components/providers/UserHistories";

// popup display duration when auto-playing the tour
const playDelay = 3000;
@@ -19,17 +56,24 @@ const playDelay = 3000;
export default {
    components: {
        TourStep,
        CurrentUser,
        UserHistories,
    },
    props: {
        steps: {
            type: Array,
            required: true,
        },
        requirements: {
            type: Array,
            required: true,
        },
    },
    data() {
        return {
            currentIndex: -1,
            isPlaying: false,
            showRequirementDialog: true,
        };
    },
    computed: {
@@ -60,6 +104,26 @@ export default {
                this.next();
            }
        },
        loginRequired(user) {
            return this.requirements.indexOf("logged_in") >= 0 && user.isAnonymous;
        },
        adminRequired(user) {
            return this.requirements.indexOf("admin") >= 0 && !user.is_admin;
        },
        newHistoryRequired(history) {
            const hasNewNistoryRequirement = this.requirements.indexOf("new_history") >= 0;
            if (!hasNewNistoryRequirement) {
                return false;
            } else if (history && history.size != 0) {
                // TODO: better estimate for whether the history is new.
                return true;
            } else {
                return false;
            }
        },
        createNewHistory(handlers) {
            handlers.createNewHistory();
        },
        async next() {
            // do post-actions
            if (this.currentStep && this.currentStep.onNext) {
+2 −1
Original line number Diff line number Diff line
@@ -121,5 +121,6 @@ export async function runTour(tourId, tourData = null) {
            },
        });
    });
    return mountTour({ steps });
    const requirements = tourData.requirements || [];
    return mountTour({ steps, requirements });
}
+7 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ from typing import (
import yaml
from pydantic import parse_obj_as

from galaxy.exceptions import ObjectNotFound
from galaxy.util import config_directories_from_setting
from ._interface import ToursRegistry
from ._schema import TourList
@@ -32,6 +33,9 @@ def load_tour_steps(contents_dict, warn=None):
    warn = warn or noop_warn
    #  Some of this can be done on the clientside.  Maybe even should?
    title_default = contents_dict.get("title_default")
    if "requirements" not in contents_dict:
        contents_dict["requirements"] = []

    for step in contents_dict["steps"]:
        # Remove attributes no longer used, so they are attempted to be
        # validated.
@@ -94,6 +98,7 @@ class ToursRegistryImpl:
                "name": self.tours[k].get("name"),
                "description": self.tours[k].get("description"),
                "tags": self.tours[k].get("tags"),
                "requirements": self.tours[k].get("requirements"),
            }
            tours.append(tourdata)
        return parse_obj_as(TourList, tours)
@@ -102,6 +107,8 @@ class ToursRegistryImpl:
        """Return tour contents."""
        # Extra format translation could happen here (like the previous intro_to_tour)
        # For now just return the loaded contents.
        if tour_id not in self.tours:
            raise ObjectNotFound(f"tour {tour_id} not found")
        return self.tours.get(tour_id)

    def load_tour(self, tour_id):
+13 −0
Original line number Diff line number Diff line
from enum import Enum
from typing import (
    List,
    Optional,
@@ -10,10 +11,22 @@ from pydantic import (
)


class Requirement(str, Enum):
    """Available types of job sources (model classes) that produce dataset collections."""

    LOGGED_IN = "logged_in"
    NEW_HISTORY = "new_history"
    ADMIN = "admin"


class TourCore(BaseModel):
    name: str = Field(title="Name", description="Name of tour")
    description: str = Field(title="Description", description="Tour description")
    tags: List[str] = Field(title="Tags", description="Topic topic tags")
    requirements: List[Requirement] = Field(title="Requirements", description="Requirements to run the tour.")

    class Config:
        use_enum_values = True  # when using .dict()


class Tour(TourCore):