Explorar el Código

[frontend] Replace outdated Shepherd tool used for the welcome tour

This replaces shepherd with react-joyride which is a more modern React based solution for welcome tours. I've also adjusted the welcome tour steps to make more sense.
Johan Åhlén hace 2 años
padre
commit
5ae2e05b78

+ 31 - 0
desktop/core/src/desktop/js/reactComponents/WelcomeTour/WelcomeTour.module.scss

@@ -0,0 +1,31 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// 'License'); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an 'AS IS' BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+@import '../../components/styles/mixins';
+@import '../../components/styles/variables';
+
+/* stylelint-disable */
+:export {
+  primaryColor: $hue-primary-color-dark;
+  overlayColor: rgba($fluidx-black, 0.2);
+  tourZIndex: 2000;
+  borderRadius: $border-radius-base;
+  buttonFontSize: $font-size-base;
+  buttonPadding: 6px 12px;
+  buttonLineHeight: 20px;
+  backButtonBorder: 1px solid $fluidx-gray-300;
+}
+/* stylelint-enable */

+ 26 - 0
desktop/core/src/desktop/js/reactComponents/WelcomeTour/WelcomeTour.scss

@@ -0,0 +1,26 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// 'License'); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an 'AS IS' BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+@import '../../components/styles/mixins';
+@import '../../components/styles/variables';
+
+.react-joyride__tooltip {
+  h3 {
+    font-size: $fluidx-heading-h3-size;
+    line-height: $fluidx-heading-h3-line-height;
+    font-weight: $fluidx-heading-h3-weight;
+  }
+}

+ 37 - 0
desktop/core/src/desktop/js/reactComponents/WelcomeTour/WelcomeTour.test.tsx

@@ -0,0 +1,37 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import React from 'react';
+import { act, render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom';
+
+import huePubSub from 'utils/huePubSub';
+
+import WelcomeTour from './WelcomeTour';
+
+describe('WelcomeTour', () => {
+  test('it should show the welcome tour on huePubSub event', async () => {
+    render(<WelcomeTour />);
+    expect(screen.queryByText(/Welcome to Hue 4!/)).not.toBeInTheDocument();
+
+    await act(async () => {
+      huePubSub.publish('show.welcome.tour');
+      await new Promise(process.nextTick);
+    });
+
+    expect(screen.queryByText(/Welcome to Hue 4!/)).toBeInTheDocument();
+  });
+});

+ 224 - 0
desktop/core/src/desktop/js/reactComponents/WelcomeTour/WelcomeTour.tsx

@@ -0,0 +1,224 @@
+// Licensed to Cloudera, Inc. under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  Cloudera, Inc. licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import React, { ReactNode, useState } from 'react';
+import Joyride from 'react-joyride';
+
+import { post } from 'api/utils';
+import { hueWindow } from 'types/types';
+import I18n from 'utils/i18n';
+import { useHuePubSub } from '../useHuePubSub';
+
+import './WelcomeTour.scss';
+import scssVariables from './WelcomeTour.module.scss';
+
+const {
+  backButtonBorder,
+  borderRadius,
+  buttonFontSize,
+  buttonLineHeight,
+  buttonPadding,
+  overlayColor,
+  primaryColor,
+  tourZIndex
+} = scssVariables;
+
+const getStepContent = (title?: ReactNode, text?: ReactNode) => (
+  <>
+    {title && <h3>{title}</h3>}
+    {text && <p>{text}</p>}
+  </>
+);
+
+const steps: Joyride.Step[] = [
+  {
+    content: getStepContent(
+      I18n('Welcome to Hue 4!'),
+      I18n('We want to introduce you to the new interface. It takes less than a minute. Ready?')
+    ),
+    target: 'body',
+    disableBeacon: true,
+    placement: 'center'
+  },
+  {
+    content: getStepContent(
+      I18n('A new top bar!'),
+      I18n('Do global search and view status of jobs and notifications on the right.')
+    ),
+    target: '.navbar-default',
+    disableBeacon: true,
+    placement: 'bottom'
+  },
+  {
+    content: getStepContent(
+      I18n('Sidebar for navigation'),
+      I18n('Open apps and browsers, get help and manage your user profile.')
+    ),
+    target: '.sidebar',
+    disableBeacon: true,
+    placement: 'right'
+  },
+  {
+    content: getStepContent(
+      I18n('Left Assist Panel'),
+      I18n(
+        'Discover data sources with the improved data assist panel. Remember to right-click items for more!'
+      )
+    ),
+    target: '.left-panel',
+    disableBeacon: true,
+    placement: 'right'
+  },
+  {
+    content: getStepContent(
+      undefined,
+      `${I18n('This is the main attraction, where your selected app runs.')}\n${I18n(
+        'Hover on the app name to star it as your favorite application.'
+      )}`
+    ),
+    target: '.page-content',
+    disableBeacon: true,
+    placement: 'bottom',
+    styles: {
+      tooltip: {
+        marginTop: '100px'
+      }
+    }
+  },
+  {
+    content: getStepContent(
+      I18n('Right Assist Panel'),
+      I18n(
+        'Some apps have a right panel with additional information to assist you in your data discovery.'
+      )
+    ),
+    target: '.right-panel',
+    disableBeacon: true,
+    placement: 'left'
+  },
+  {
+    content: (
+      <>
+        <p>
+          {I18n(
+            'This ends the tour. To see it again, click Welcome Tour from the help section in the sidebar.'
+          )}
+        </p>
+        <p>
+          {I18n('And now go ')}
+          <b>{I18n('Query, Explore, Repeat')}</b>!
+        </p>
+      </>
+    ),
+    target: 'body',
+    disableBeacon: true,
+    placement: 'center'
+  }
+];
+
+if ((window as hueWindow).USER_IS_ADMIN) {
+  steps.splice(3, 0, {
+    content: getStepContent(
+      I18n('Administration'),
+      I18n(
+        'As a superuser, you can check system configuration from the user menu and install sample data and jobs for your users.'
+      )
+    ),
+    target: '.server-position-pointer-welcome-tour',
+    disableBeacon: true,
+    placement: 'right-end'
+  });
+}
+
+const styles: Partial<Joyride.Styles> = {
+  options: {
+    overlayColor,
+    primaryColor,
+    zIndex: parseInt(tourZIndex) || 1 // the fallback to 1 is for testing where it doesn't pick up the scss vars properly
+  },
+  buttonBack: {
+    border: backButtonBorder,
+    borderRadius,
+    fontSize: buttonFontSize,
+    lineHeight: buttonLineHeight,
+    padding: buttonPadding
+  },
+  buttonNext: {
+    borderRadius,
+    fontSize: buttonFontSize,
+    lineHeight: buttonLineHeight,
+    padding: buttonPadding
+  },
+  tooltip: {
+    borderRadius
+  },
+  spotlight: {
+    borderRadius: 0
+  }
+};
+
+export const WelcomeTour = (): JSX.Element => {
+  const [run, setRun] = useState(false);
+  const [joyrideHelpers, setJoyrideHelpers] = useState<Joyride.StoreHelpers>();
+
+  useHuePubSub({
+    topic: 'show.welcome.tour',
+    callback: () => {
+      setRun(true);
+    }
+  });
+
+  const onStateChange: Joyride.Callback = ({ action }) => {
+    if (action === 'close' || action === 'reset') {
+      setRun(false);
+      if (joyrideHelpers) {
+        joyrideHelpers.reset(false);
+      }
+
+      // While migrating the old welcome tour I noticed that we no longer start the welcome tour
+      // automatically for new users, this was done intentionally in commit:
+      // https://github.com/cloudera/hue/commit/f54d0e23fa1105b1bbf8c2cd8f830c2835572be1
+      // The user preference is in place in the backend so if we ever want to revert that change
+      // we should uncomment the below code and set the initial "run" state based on the value
+      // of the preference.
+
+      // post('/desktop/api2/user_preferences/is_welcome_tour_seen', {
+      //   set: 'seen'
+      // });
+    }
+  };
+
+  return (
+    <Joyride
+      steps={steps}
+      run={run}
+      disableScrolling={true}
+      continuous={true}
+      spotlightPadding={0}
+      callback={onStateChange}
+      getHelpers={setJoyrideHelpers}
+      locale={{
+        back: I18n('Back'),
+        close: I18n('Close'),
+        last: I18n('Close'),
+        next: I18n('Next')
+      }}
+      styles={styles}
+    />
+  );
+};
+
+export default WelcomeTour;

+ 3 - 0
desktop/core/src/desktop/js/reactComponents/imports.js

@@ -23,6 +23,9 @@ export async function loadComponent(name) {
     case 'FileChooserWithButton':
       return (await import('./FileChooser/FileChooserWithButton/FileChooserWithButton')).default;
 
+    case 'WelcomeTour':
+      return (await import('./WelcomeTour/WelcomeTour')).default;
+
     default:
       console.error(`A placeholder component is rendered because you probably forgot to include your new component in the 
       loadComponent function of reactComponents/imports.js`);

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue3-extra.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
desktop/core/src/desktop/static/desktop/ext/js/shepherd.min.js


+ 0 - 408
desktop/core/src/desktop/static/desktop/less/components/hue-shepherd.less

@@ -1,408 +0,0 @@
-/*
- Licensed to Cloudera, Inc. under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  Cloudera, Inc. licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-top.shepherd-target-attached-left .shepherd-content::before,
-.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-top.shepherd-target-attached-right .shepherd-content::before,
-.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-bottom.shepherd-target-attached-left .shepherd-content::before,
-.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-bottom.shepherd-target-attached-right .shepherd-content::before {
-  display: none;
-}
-
-.shepherd-element,
-.shepherd-element::after,
-.shepherd-element::before,
-.shepherd-element *,
-.shepherd-element *::after,
-.shepherd-element *::before {
-  box-sizing: border-box;
-}
-
-.shepherd-element {
-  position: absolute;
-  display: none;
-}
-
-.shepherd-element.shepherd-open {
-  display: block;
-}
-
-.shepherd-element.shepherd-theme-hue {
-  max-height: 100%;
-  border-radius: 0;
-  z-index: 9999;
-  max-width: 24em;
-  font-size: 1em;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content {
-  .hue-box-shadow-bottom;
-
-  border-radius: 4px;
-  padding: 0;
-  position: relative;
-  font-family: inherit;
-  background: @cui-gray-900;
-  color: @cui-gray-200;
-  font-size: 1.1em;
-  line-height: 1.5em;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content::before {
-  content: "";
-  display: block;
-  position: absolute;
-  width: 0;
-  height: 0;
-  border-color: transparent;
-  border-width: 16px;
-  border-style: solid;
-  pointer-events: none;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-center .shepherd-content {
-  margin-bottom: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-center .shepherd-content::before {
-  top: 100%;
-  left: 50%;
-  margin-left: -16px;
-  border-top-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-center .shepherd-content {
-  margin-top: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-center .shepherd-content::before {
-  bottom: 100%;
-  left: 50%;
-  margin-left: -16px;
-  border-bottom-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-right.shepherd-element-attached-middle .shepherd-content {
-  margin-right: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-right.shepherd-element-attached-middle .shepherd-content::before {
-  left: 100%;
-  top: 50%;
-  margin-top: -16px;
-  border-left-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-left.shepherd-element-attached-middle .shepherd-content {
-  margin-left: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-left.shepherd-element-attached-middle .shepherd-content::before {
-  right: 100%;
-  top: 50%;
-  margin-top: -16px;
-  border-right-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-left.shepherd-target-attached-center .shepherd-content {
-  left: -32px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-right.shepherd-target-attached-center .shepherd-content {
-  left: 32px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-middle .shepherd-content {
-  margin-top: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-middle .shepherd-content::before {
-  bottom: 100%;
-  left: 16px;
-  border-bottom-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-middle .shepherd-content {
-  margin-top: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-middle .shepherd-content::before {
-  bottom: 100%;
-  right: 16px;
-  border-bottom-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-middle .shepherd-content {
-  margin-bottom: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-middle .shepherd-content::before {
-  top: 100%;
-  left: 16px;
-  border-top-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-middle .shepherd-content {
-  margin-bottom: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-middle .shepherd-content::before {
-  top: 100%;
-  right: 16px;
-  border-top-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-bottom .shepherd-content {
-  margin-top: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-bottom .shepherd-content::before {
-  bottom: 100%;
-  left: 16px;
-  border-bottom-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-bottom .shepherd-content {
-  margin-top: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-bottom .shepherd-content::before {
-  bottom: 100%;
-  right: 16px;
-  border-bottom-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-top .shepherd-content {
-  margin-bottom: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-top .shepherd-content::before {
-  top: 100%;
-  left: 16px;
-  border-top-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-top .shepherd-content {
-  margin-bottom: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-top .shepherd-content::before {
-  top: 100%;
-  right: 16px;
-  border-top-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-left .shepherd-content {
-  margin-right: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-left .shepherd-content::before {
-  top: 16px;
-  left: 100%;
-  border-left-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-right .shepherd-content {
-  margin-left: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-right .shepherd-content::before {
-  top: 16px;
-  right: 100%;
-  border-right-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-left .shepherd-content {
-  margin-right: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-right.shepherd-target-attached-left .shepherd-content::before {
-  bottom: 16px;
-  left: 100%;
-  border-left-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-right .shepherd-content {
-  margin-left: 16px;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-bottom.shepherd-element-attached-left.shepherd-target-attached-right .shepherd-content::before {
-  bottom: 16px;
-  right: 100%;
-  border-right-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-center.shepherd-has-title .shepherd-content::before,
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-right.shepherd-target-attached-bottom.shepherd-has-title .shepherd-content::before,
-.shepherd-element.shepherd-theme-hue.shepherd-element-attached-top.shepherd-element-attached-left.shepherd-target-attached-bottom.shepherd-has-title .shepherd-content::before {
-  border-bottom-color: @cui-gray-900;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-has-title .shepherd-content header {
-  background: @cui-gray-900;
-  padding: 1em;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-has-title .shepherd-content header a.shepherd-cancel-link {
-  padding: 0;
-  margin-bottom: 0;
-}
-
-.shepherd-element.shepherd-theme-hue.shepherd-has-cancel-link .shepherd-content header h3 {
-  float: left;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content * {
-  font-size: inherit;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content header {
-  *zoom: 1;
-  border-radius: 0;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content header::after {
-  content: "";
-  display: table;
-  clear: both;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content header h3 {
-  margin: 0;
-  line-height: 1;
-  font-weight: normal;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content header a.shepherd-cancel-link {
-  float: right;
-  text-decoration: none;
-  font-size: 1.25em;
-  line-height: 0.8em;
-  font-weight: normal;
-  color: @cui-white;
-  opacity: 0.25;
-  position: relative;
-  top: 0.1em;
-  padding: 0.8em;
-  margin-bottom: -0.8em;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content header a.shepherd-cancel-link:hover {
-  opacity: 1;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content .shepherd-text {
-  padding: 1em;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content .shepherd-text p {
-  margin: 0 0 0.5em 0;
-  line-height: 1.3em;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content .shepherd-text p:last-child {
-  margin-bottom: 0;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content footer {
-  padding: 0 1em 1em;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content footer .shepherd-buttons {
-  text-align: right;
-  list-style: none;
-  padding: 0;
-  margin: 0;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content footer .shepherd-buttons li {
-  display: inline;
-  padding: 0;
-  margin: 0;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content footer .shepherd-buttons li .shepherd-button {
-  display: inline-block;
-  vertical-align: middle;
-  *vertical-align: auto;
-  *zoom: 1;
-  cursor: pointer;
-  border: 0;
-  margin: 0 0.5em 0 0;
-  font-family: inherit;
-  font-size: 14px;
-  line-height: 20px;
-  padding-left: 12px;
-  padding-right: 12px;
-  border-radius: 4px;
-  background: @hue-primary-color-dark;
-  color: @cui-white;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content footer .shepherd-buttons li .shepherd-button.shepherd-button-secondary {
-  background: @cui-gray-200;
-  color: @cui-gray-700;
-}
-
-.shepherd-element.shepherd-theme-hue .shepherd-content footer .shepherd-buttons li:last-child .shepherd-button {
-  margin-right: 0;
-}
-
-.shepherd-start-tour-button.shepherd-theme-hue {
-  display: inline-block;
-  vertical-align: middle;
-  *vertical-align: auto;
-  *zoom: 1;
-  cursor: pointer;
-  border: 0;
-  margin: 0 0.5em 0 0;
-  font-family: inherit;
-  font-size: 14px;
-  line-height: 20px;
-  padding-left: 12px;
-  padding-right: 12px;
-  border-radius: 4px;
-  background: @hue-primary-color-dark;
-  color: @cui-white;
-}
-
-.shepherd-active {
-  .shepherd-step {
-    z-index: 1012;
-  }
-
-  .shepherd-target {
-    &.shepherd-enabled {
-      background-color: white;
-      z-index: 1011;
-    }
-  }
-
-  .shepherd-backdrop {
-    position: fixed;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    background-color: @cui-white;
-    @opacity: 65;
-
-    opacity: @opacity / 100;
-    filter: alpha(opacity=@opacity);
-    z-index: 1010;
-  }
-}

+ 0 - 1
desktop/core/src/desktop/static/desktop/less/hue-cross-version.less

@@ -36,7 +36,6 @@
 @import "components/hue-scrollbar.less";
 @import "components/hue-selectize.less";
 @import "components/hue-selector.less";
-@import "components/hue-shepherd.less";
 @import "components/hue-simple-ace.less";
 @import "components/hue-snippet-editor-actions.less";
 @import "components/hue-snippet-execute-actions.less";

+ 30 - 13
desktop/core/src/desktop/templates/global_js_constants.mako

@@ -251,9 +251,10 @@
 
   // TODO: Replace with json import
   window.HUE_I18n = {
-    '1 hour':  '${ _('1 hour') }',
-    '1 week':  '${ _('1 week') }',
-    '8 hours':  '${ _('8 hours') }',
+    '1 hour': '${ _('1 hour') }',
+    '1 week': '${ _('1 week') }',
+    '8 hours': '${ _('8 hours') }',
+    'A new top bar!': '${ _('A new top bar!') }',
     'Active cluster': '${ _('Active cluster') }',
     'Active compute': '${ _('Active compute') }',
     'Active database': '${ _('Active database') }',
@@ -266,18 +267,20 @@
     'Add tags...': '${ _('Add tags...') }',
     'Add': '${ _('Add') }',
     'Admin': '${ _('Admin') }',
-    'Administration': '${ _('Administration') }',
     'Administer Server': '${ _('Administer Server') }',
     'Administer Users': '${ _('Administer Users') }',
-    'aggregate': '${ _('aggregate') }',
+    'Administration': '${ _('Administration') }',
     'Aggregate': '${ _('Aggregate') }',
+    'aggregate': '${ _('aggregate') }',
     'alias': '${ _('alias') }',
     'All': '${_('All')}',
     'An error occurred refreshing the table stats. Please try again.': '${_('An error occurred refreshing the table stats. Please try again.')}',
     'Analysis was not possible for the executed query.': '${_('Analysis was not possible for the executed query.')}',
+    'And now go ': '${_('And now go ')}',
     'and': '${_('and')}',
     'Apps': '${ _('Apps') }',
     'Are you sure you want to clear the task history?': '${ _('Are you sure you want to clear the task history?') }',
+    'As a superuser, you can check system configuration from the user menu and install sample data and jobs for your users.': '${ _('As a superuser, you can check system configuration from the user menu and install sample data and jobs for your users.') }',
     'Assist': '${ _('Assist') }',
     'Assistant': '${ _('Assistant') }',
     'at cursor': '${ _('at cursor') }',
@@ -287,8 +290,8 @@
     'Bars': '${ _('Bars') }',
     'Brazil': '${ _('Brazil') }',
     'Browse column privileges': '${_('Browse column privileges')}',
-    'Browse db privileges': '${ _('Browse db privileges') }',
     'Browse DB privileges': '${_('Browse DB privileges')}',
+    'Browse db privileges': '${ _('Browse db privileges') }',
     'Browse table privileges': '${_('Browse table privileges')}',
     'Browsers': '${ _('Browsers') }',
     'Bundle': '${ _('Bundle') }',
@@ -356,8 +359,10 @@
     'dir': '${ _('dir') }',
     'Directory name': '${ _('Directory name') }',
     'Directory': '${ _('Directory') }',
+    'Discover data sources with the improved data assist panel. Remember to right-click for more!': '${ _('Discover data sources with the improved data assist panel. Remember to right-click for more!') }',
     'DistCp Job': '${_('DistCp Job')}',
     'distinct': '${ _('distinct') }',
+    'Do global search and view status of jobs and notifications on the right.': '${_('Do global search and view status of jobs and notifications on the right.')}',
     'Do you really want to delete the following document(s)?': '${ _('Do you really want to delete the following document(s)?') }',
     'Document type': '${ _('Document type') }',
     'Documentation': '${ _('Documentation') }',
@@ -404,17 +409,14 @@
     'Filter columns...': '${ _('Filter columns...') }',
     'Filter databases...': '${ _('Filter databases...') }',
     'Filter sources...': '${ _('Filter sources...') }',
-    'filter': '${ _('filter') }',
     'Filter': '${ _('Filter') }',
+    'filter': '${ _('filter') }',
     'Filter...': '${ _('Filter...') }',
     'Fix': '${ _('Fix') }',
     'Folder name': '${_('Folder name')}',
     'Foreign key': '${_('Foreign key')}',
     'Foreign keys': '${_('Foreign keys')}',
     'Format the current SQL query': '${ _('Format the current SQL query') }',
-    'Share the query selection via a link': '${ _('Share the query selection via a link') }',
-    'Share link': '${ _('Share link') }',
-    'Share as a gist': '${ _('Share as a gist') }',
     'Format': '${ _('Format') }',
     'France': '${ _('France') }',
     'Functions': '${ _('Functions') }',
@@ -433,6 +435,7 @@
     'Hide advanced': '${_('Hide advanced')}',
     'Hide Details': '${ _('Hide Details') }',
     'Hive Query': '${_('Hive Query')}',
+    'Hover on the app name to star it as your favorite application.': '${ _('Hover on the app name to star it as your favorite application.') }',
     'Identifiers': '${ _('Identifiers') }',
     'Ignore this type of error': '${_('Ignore this type of error')}',
     'Impala Query': '${_('Impala Query')}',
@@ -470,6 +473,7 @@
     'Language Reference': '${ _('Language Reference') }',
     'latitude': '${ _('latitude') }',
     'legend': '${ _('legend') }',
+    'Left Assist Panel': '${ _('Left Assist Panel') }',
     'Limit the number of results to...': '${ _('Limit the number of results to...') }',
     'limit': '${ _('limit') }',
     'Lines': '${ _('Lines') }',
@@ -503,13 +507,14 @@
     'Namespaces': '${ _('Namespaces') }',
     'New document': '${ _('New document') }',
     'New folder': '${ _('New folder') }',
+    'Next': '${ _('Next') }',
     'No clusters available': '${ _('No clusters available') }',
     'No clusters available.': '${ _('No clusters available.') }',
     'No clusters found': '${ _('No clusters found') }',
     'No columns found': '${ _('No columns found') }',
     'No computes found': '${ _('No computes found') }',
-    'No data available': '${ _('No data available') }',
     'No Data Available.': '${ _('No Data Available.') }',
+    'No data available': '${ _('No data available') }',
     'No databases found': '${ _('No databases found') }',
     'No databases found.': '${ _('No databases found.') }',
     'No documents found': '${ _('No documents found') }',
@@ -537,6 +542,7 @@
     'Oozie Bundle': '${_('Oozie Bundle')}',
     'Oozie Schedule': '${_('Oozie Schedule')}',
     'Oozie Workflow': '${_('Oozie Workflow')}',
+    'Open apps and browsers, get help and manage your user profile.': '${_('Open apps and browsers, get help and manage your user profile.')}',
     'Open cluster': '${_('Open cluster')}',
     'Open document': '${_('Open document')}',
     'Open folder': '${_('Open folder')}',
@@ -578,6 +584,7 @@
     'Query requires a select or aggregate.': '${ _('Query requires a select or aggregate.') }',
     'Query running': '${ _('Query running') }',
     'Query settings': '${ _('Query settings') }',
+    'Query, Explore, Repeat': '${ _('Query, Explore, Repeat') }',
     'queued': '${ _('queued') }',
     'Re-create session': '${ _('Re-create session') }',
     'Re-create': '${ _('Re-create') }',
@@ -591,6 +598,7 @@
     'Result image': '${ _('Result image') }',
     'result(s) copied to the clipboard' : '${ _('result(s) copied to the clipboard') }',
     'Results have expired, rerun the query if needed.': '${ _('Results have expired, rerun the query if needed.') }',
+    'Right Assist Panel': '${ _('Right Assist Panel') }',
     'Risks': '${ _('Risks') }',
     'Running': '${ _('Running') }',
     'sample query': '${ _('sample query') }',
@@ -622,6 +630,9 @@
     'Set as default application': '${_('Set as default application')}',
     'Set as default settings': '${_('Set as default settings')}',
     'Settings': '${ _('Settings') }',
+    'Share as a gist': '${ _('Share as a gist') }',
+    'Share link': '${ _('Share link') }',
+    'Share the query selection via a link': '${ _('Share the query selection via a link') }',
     'Share': '${ _('Share') }',
     'Sharing': '${ _('Sharing') }',
     'Shell Script': '${_('Shell Script')}',
@@ -635,9 +646,11 @@
     'Show row details': '${_('Show row details')}',
     'Show sample': '${_('Show sample')}',
     'Show view SQL': '${_('Show view SQL')}',
+    'Sidebar for navigation': '${_('Sidebar for navigation')}',
     'Sign out': '${ _('Sign out') }',
     'Size': '${ _('Size') }',
     'Solr Search': '${ _('Solr Search') }',
+    'Some apps have a right panel with additional information to assist you in your data discovery.': '${ _('Some apps have a right panel with additional information to assist you in your data discovery.') }',
     'Sort ascending': '${ _('Sort ascending') }',
     'Sort descending': '${ _('Sort descending') }',
     'sorting': '${ _('sorting') }',
@@ -656,8 +669,8 @@
     'Success.': '${ _('Success.') }',
     'Summary': '${_('Summary')}',
     'Table Browser': '${ _('Table Browser') }',
-    'table': '${ _('table') }',
     'Table': '${ _('Table') }',
+    'table': '${ _('table') }',
     'Tables': '${ _('Tables') }',
     'Tags can only contain 1 to 50 alphanumeric characters, _ or -.': '${ _('Tags can only contain 1 to 50 alphanumeric characters, _ or -.') }',
     'Tags could not be loaded.': '${ _('Tags could not be loaded.') }',
@@ -678,7 +691,9 @@
     'There was a problem loading the indexes': '${ _('There was a problem loading the indexes') }',
     'There was a problem loading the table preview': '${ _('There was a problem loading the table preview') }',
     'There was an error loading the document.': '${ _('There was an error loading the document.') }',
+    'This ends the tour. To see it again, click Welcome Tour from the help section in the sidebar.': '${ _('This ends the tour. To see it again, click Welcome Tour from the help section in the sidebar.') }',
     'This field does not support stats': '${ _('This field does not support stats') }',
+    'This is the main attraction, where your selected app runs.': '${ _('This is the main attraction, where your selected app runs.') }',
     'This will sync missing tables.': '${ _('This will sync missing tables.') }',
     'Timeline Chart': '${ _('Timeline Chart') }',
     'Timeline': '${ _('Timeline') }',
@@ -711,7 +726,9 @@
     'view': '${ _('view') }',
     'Views': '${ _('Views') }',
     'virtual': '${ _('virtual') }',
+    'We want to introduce you to the new interface. It takes less than a minute. Ready?': '${ _('We want to introduce you to the new interface. It takes less than a minute. Ready?') }',
     'Welcome Tour': '${ _('Welcome Tour') }',
+    'Welcome to Hue 4!': '${ _('Welcome to Hue 4!') }',
     'With grant option': '${ _('With grant option') }',
     'With grant': '${ _('With grant') }',
     'Workflow': '${ _('Workflow') }',
@@ -719,7 +736,7 @@
     'x-axis': '${ _('x-axis') }',
     'y-axis': '${ _('y-axis') }',
     'Yes': '${ _('Yes') }',
-    'Yes, delete': '${ _('Yes, delete') }',
+    'Yes, delete': '${ _('Yes, delete') }'
   };
   window.HUE_LANG = '${get_language()}';
 

+ 5 - 83
desktop/core/src/desktop/templates/hue.mako

@@ -21,7 +21,7 @@
   from desktop.auth.backend import is_admin
   from desktop.conf import ENABLE_HUE_5, has_multi_clusters
   from desktop.lib.i18n import smart_unicode
-  from desktop.models import PREFERENCE_IS_WELCOME_TOUR_SEEN, hue_version
+  from desktop.models import hue_version
   from desktop.views import _ko, commonshare, login_modal
   from desktop.webpack_utils import get_hue_bundles
 
@@ -141,7 +141,8 @@ ${ hueIcons.symbols() }
 
   <div class="main-page">
     <AppBanner data-reactcomponent='AppBanner'></AppBanner>
-    <AlertComponent data-reactcomponent='AlertComponent' ></AlertComponent> 
+    <AlertComponent data-reactcomponent='AlertComponent'></AlertComponent>
+    <WelcomeTour data-reactcomponent='WelcomeTour'></WelcomeTour>
 
     <nav class="navbar navbar-default">
       <div class="navbar-inner top-nav">
@@ -305,10 +306,9 @@ ${ commonshare() | n,unicode }
 
 <script src="${ static('desktop/js/polyfills.js') }"></script>
 <script src="${ static('desktop/ext/js/tether.js') }"></script>
-<script src="${ static('desktop/ext/js/shepherd.min.js') }"></script>
 <script src="${ static('desktop/ext/js/moment-with-locales.min.js') }"></script>
-<script src="${ static('desktop/ext/js/moment-timezone-with-data.min.js') }" type="text/javascript" charset="utf-8"></script>
-<script src="${ static('desktop/ext/js/tzdetect.js') }" type="text/javascript" charset="utf-8"></script>
+<script src="${ static('desktop/ext/js/moment-timezone-with-data.min.js') }"></script>
+<script src="${ static('desktop/ext/js/tzdetect.js') }"></script>
 
 <script src="${ static('desktop/ext/js/bootstrap-fileupload.js') }"></script>
 <script src="${ static('desktop/js/bootstrap-tooltip.js') }"></script>
@@ -339,84 +339,6 @@ ${ smart_unicode(login_modal(request).content) | n,unicode }
 
 <iframe id="zoomDetectFrame" style="width: 250px; display: none" ></iframe>
 
-<script type="text/javascript">
-  $(document).ready(function () {
-    var tour = new Shepherd.Tour({
-      defaults: {
-        classes: 'shepherd-theme-hue',
-        showCancelLink: true
-      }
-    });
-
-    tour.addStep('welcome', {
-      text: '<b>${ _ko('Welcome to Hue 4!') }</b><br><br>${ _ko('We want to introduce you to the new interface. It takes less than a minute. Ready? ') }'
-    });
-
-    tour.addStep('topnav', {
-      text: '${ _ko('A new nav bar and big blue button!') }<br><br>${ _ko('Open Hue to your favorite app, select other apps from the blue button, do global search, and view notification panels at right.') }',
-      attachTo: '.navbar-default bottom'
-    });
-
-    %if is_admin(user):
-      tour.addStep('admin', {
-        text: '${ _ko('As a superuser, you can check system configuration from the user menu and install sample data and jobs for your users.') }',
-        attachTo: '.server-position-pointer-welcome-tour left'
-      });
-    %endif
-
-    tour.addStep('leftpanel', {
-      text: '${ _ko('Discover data sources with the improved data assist panel. Remember to right-click for more!') }',
-      attachTo: '.left-panel right'
-    });
-
-    tour.addStep('pagecontent', {
-      text: '${ _ko('This is the main attraction, where your selected app runs.') }<br>${ _ko('Hover on the app name to star it as your favorite application.') }',
-      attachTo: '.page-content center'
-    });
-
-    tour.addStep('rightpanel', {
-      text: '${ _ko('Some apps have a right panel with additional information to assist you in your data discovery.') }',
-      attachTo: '.right-panel left'
-    });
-
-    tour.addStep('bye', {
-      text: '${ _ko('This ends the tour. To see it again, click Welcome Tour from the username drop down.') }<br><br>${ _ko('And now go ') }<b>${ _ko('Query, Explore, Repeat') }</b>!'
-    });
-
-    var closeTourOnEsc = function (e) {
-      if (e.keyCode === 27) {
-        tour.cancel();
-      }
-    };
-
-    % if False and (is_demo or not user_preferences.get(PREFERENCE_IS_WELCOME_TOUR_SEEN)):
-      $(document).on('keyup', closeTourOnEsc);
-      $(document).on('click', '.shepherd-backdrop', tour.cancel);
-      tour.start();
-    % endif
-
-
-    tour.on('complete', function () {
-      $.post('/desktop/api2/user_preferences/${ PREFERENCE_IS_WELCOME_TOUR_SEEN }', {
-        'set': 'seen'
-      });
-      $(document).off('keyup', closeTourOnEsc);
-    });
-
-    tour.on('cancel', function () {
-      $.post('/desktop/api2/user_preferences/${ PREFERENCE_IS_WELCOME_TOUR_SEEN }', {
-        'set': 'seen'
-      });
-      $(document).off('keyup', closeTourOnEsc);
-    });
-
-    huePubSub.subscribe('show.welcome.tour', function () {
-      $(document).on('keyup', closeTourOnEsc);
-      tour.start();
-    });
-  });
-</script>
-
 ${ commonHeaderFooterComponents.footer(messages) }
 
 <div class="monospace-preload" style="opacity: 0; height: 0; width: 0;">

+ 179 - 11
package-lock.json

@@ -48,6 +48,7 @@
         "react": "18.2.0",
         "react-dom": "18.2.0",
         "react-i18next": "11.18.6",
+        "react-joyride": "2.7.0",
         "regenerator-runtime": "0.13.7",
         "removeNPMAbsolutePaths": "1.0.6",
         "sanitize-html": "2.7.2",
@@ -2553,6 +2554,39 @@
         "sql-formatter": "bin/sqlfmt.js"
       }
     },
+    "node_modules/@gilbarbara/deep-equal": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.3.1.tgz",
+      "integrity": "sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw=="
+    },
+    "node_modules/@gilbarbara/helpers": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/@gilbarbara/helpers/-/helpers-0.9.0.tgz",
+      "integrity": "sha512-hl96DIoGgyJkjyiOGwEC6kZnYCsYSjhR8QTbvl7+i74fdllPgJeq4oCLH7HPiFGtnhCh4RuXTa4fmfy/8McAVQ==",
+      "dependencies": {
+        "@gilbarbara/types": "^0.2.2",
+        "is-lite": "^1.2.0"
+      }
+    },
+    "node_modules/@gilbarbara/types": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/@gilbarbara/types/-/types-0.2.2.tgz",
+      "integrity": "sha512-QuQDBRRcm1Q8AbSac2W1YElurOhprj3Iko/o+P1fJxUWS4rOGKMVli98OXS7uo4z+cKAif6a+L9bcZFSyauQpQ==",
+      "dependencies": {
+        "type-fest": "^4.1.0"
+      }
+    },
+    "node_modules/@gilbarbara/types/node_modules/type-fest": {
+      "version": "4.7.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.7.1.tgz",
+      "integrity": "sha512-iWr8RUmzAJRfhZugX9O7nZE6pCxDU8CZ3QxsLuTnGcBLJpCaP2ll3s4eMTBoFnU/CeXY/5rfQSuAEsTGJO4y8A==",
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/@istanbuljs/load-nyc-config": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@@ -3863,8 +3897,7 @@
     "node_modules/@types/prop-types": {
       "version": "15.7.5",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
-      "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
-      "dev": true
+      "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
     },
     "node_modules/@types/qs": {
       "version": "6.9.4",
@@ -3876,7 +3909,6 @@
       "version": "18.0.20",
       "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.20.tgz",
       "integrity": "sha512-MWul1teSPxujEHVwZl4a5HxQ9vVNsjTchVA+xRqv/VYGCuKGAU6UhfrTdF5aBefwD1BHUD8i/zq+O/vyCm/FrA==",
-      "dev": true,
       "dependencies": {
         "@types/prop-types": "*",
         "@types/scheduler": "*",
@@ -3895,8 +3927,7 @@
     "node_modules/@types/react/node_modules/csstype": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
-      "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==",
-      "dev": true
+      "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
     },
     "node_modules/@types/sanitize-html": {
       "version": "1.27.0",
@@ -3910,8 +3941,7 @@
     "node_modules/@types/scheduler": {
       "version": "0.16.2",
       "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
-      "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
-      "dev": true
+      "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
     },
     "node_modules/@types/sizzle": {
       "version": "2.3.3",
@@ -7171,6 +7201,11 @@
       "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
       "dev": true
     },
+    "node_modules/deep-diff": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz",
+      "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg=="
+    },
     "node_modules/deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -7178,9 +7213,9 @@
       "dev": true
     },
     "node_modules/deepmerge": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
-      "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+      "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -8343,6 +8378,11 @@
         "node": ">=8"
       }
     },
+    "node_modules/exenv": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
+      "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
+    },
     "node_modules/exit": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -9940,6 +9980,11 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-lite": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-1.2.0.tgz",
+      "integrity": "sha512-Q9EaBEC0QV44D9iyoLMJQPEF2qMOG3TgfPCm1/lnorU5Y0PJbEqlaqX0vSBxVnxqL/m2rE4ZqRhe2OEAgVdJHA=="
+    },
     "node_modules/is-negative-zero": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
@@ -13296,7 +13341,6 @@
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -14160,6 +14204,21 @@
         "node": ">= 6"
       }
     },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/prop-types/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
     "node_modules/prr": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -14866,6 +14925,43 @@
         "react": "^18.2.0"
       }
     },
+    "node_modules/react-floater": {
+      "version": "0.7.6",
+      "resolved": "https://registry.npmjs.org/react-floater/-/react-floater-0.7.6.tgz",
+      "integrity": "sha512-tt/15k/HpaShbtvWCwsQYLR+ebfUuYbl+oAUJ3DcEDkgYKeUcSkDey2PdAIERdVwzdFZANz47HbwoET2/Rduxg==",
+      "dependencies": {
+        "deepmerge": "^4.2.2",
+        "exenv": "^1.2.2",
+        "is-lite": "^0.8.2",
+        "popper.js": "^1.16.0",
+        "prop-types": "^15.8.1",
+        "react-proptype-conditional-require": "^1.0.4",
+        "tree-changes": "^0.9.1"
+      },
+      "peerDependencies": {
+        "react": "15 - 18",
+        "react-dom": "15 - 18"
+      }
+    },
+    "node_modules/react-floater/node_modules/@gilbarbara/deep-equal": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.1.2.tgz",
+      "integrity": "sha512-jk+qzItoEb0D0xSSmrKDDzf9sheQj/BAPxlgNxgmOaA3mxpUa6ndJLYGZKsJnIVEQSD8zcTbyILz7I0HcnBCRA=="
+    },
+    "node_modules/react-floater/node_modules/is-lite": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-0.8.2.tgz",
+      "integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw=="
+    },
+    "node_modules/react-floater/node_modules/tree-changes": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.9.3.tgz",
+      "integrity": "sha512-vvvS+O6kEeGRzMglTKbc19ltLWNtmNt1cpBoSYLj/iEcPVvpJasemKOlxBrmZaCtDJoF+4bwv3m01UKYi8mukQ==",
+      "dependencies": {
+        "@gilbarbara/deep-equal": "^0.1.1",
+        "is-lite": "^0.8.2"
+      }
+    },
     "node_modules/react-i18next": {
       "version": "11.18.6",
       "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz",
@@ -14887,12 +14983,65 @@
         }
       }
     },
+    "node_modules/react-innertext": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/react-innertext/-/react-innertext-1.1.5.tgz",
+      "integrity": "sha512-PWAqdqhxhHIv80dT9znP2KvS+hfkbRovFp4zFYHFFlOoQLRiawIic81gKb3U1wEyJZgMwgs3JoLtwryASRWP3Q==",
+      "peerDependencies": {
+        "@types/react": ">=0.0.0 <=99",
+        "react": ">=0.0.0 <=99"
+      }
+    },
     "node_modules/react-is": {
       "version": "17.0.2",
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
       "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
       "dev": true
     },
+    "node_modules/react-joyride": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/react-joyride/-/react-joyride-2.7.0.tgz",
+      "integrity": "sha512-fWcIKhat6okO4gLXMz8SRUTIQKmh3dHGzsEQxHVwGNBBFd3z/KQMYVu82dBX448ASTmSG1OJhA7lqBmKX7OQVA==",
+      "dependencies": {
+        "@gilbarbara/deep-equal": "^0.3.1",
+        "@gilbarbara/helpers": "^0.9.0",
+        "deep-diff": "^1.0.2",
+        "deepmerge": "^4.3.1",
+        "is-lite": "^1.2.0",
+        "react-floater": "^0.7.6",
+        "react-innertext": "^1.1.5",
+        "react-is": "^16.13.1",
+        "scroll": "^3.0.1",
+        "scrollparent": "^2.1.0",
+        "tree-changes": "^0.11.1",
+        "type-fest": "^4.7.1"
+      },
+      "peerDependencies": {
+        "react": "15 - 18",
+        "react-dom": "15 - 18"
+      }
+    },
+    "node_modules/react-joyride/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "node_modules/react-joyride/node_modules/type-fest": {
+      "version": "4.7.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.7.1.tgz",
+      "integrity": "sha512-iWr8RUmzAJRfhZugX9O7nZE6pCxDU8CZ3QxsLuTnGcBLJpCaP2ll3s4eMTBoFnU/CeXY/5rfQSuAEsTGJO4y8A==",
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/react-proptype-conditional-require": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz",
+      "integrity": "sha512-nopsRn7KnGgazBe2c3H2+Kf+Csp6PGDRLiBkYEDMKY8o/EIgft/WnIm/OnAKTawZiLnJXHAqhpFBddvs6NiXlw=="
+    },
     "node_modules/read-installed": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz",
@@ -15499,6 +15648,11 @@
         "url": "https://opencollective.com/webpack"
       }
     },
+    "node_modules/scroll": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/scroll/-/scroll-3.0.1.tgz",
+      "integrity": "sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg=="
+    },
     "node_modules/scroll-into-view-if-needed": {
       "version": "2.2.29",
       "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz",
@@ -15507,6 +15661,11 @@
         "compute-scroll-into-view": "^1.0.17"
       }
     },
+    "node_modules/scrollparent": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.1.0.tgz",
+      "integrity": "sha512-bnnvJL28/Rtz/kz2+4wpBjHzWoEzXhVg/TE8BeVGJHUqE8THNIRnDxDWMktwM+qahvlRdvlLdsQfYe+cuqfZeA=="
+    },
     "node_modules/select": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
@@ -17059,6 +17218,15 @@
         "node": ">=8"
       }
     },
+    "node_modules/tree-changes": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.11.2.tgz",
+      "integrity": "sha512-4gXlUthrl+RabZw6lLvcCDl6KfJOCmrC16BC5CRdut1EAH509Omgg0BfKLY+ViRlzrvYOTWR0FMS2SQTwzumrw==",
+      "dependencies": {
+        "@gilbarbara/deep-equal": "^0.3.1",
+        "is-lite": "^1.2.0"
+      }
+    },
     "node_modules/treeify": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz",

+ 1 - 0
package.json

@@ -69,6 +69,7 @@
     "react": "18.2.0",
     "react-dom": "18.2.0",
     "react-i18next": "11.18.6",
+    "react-joyride": "2.7.0",
     "regenerator-runtime": "0.13.7",
     "removeNPMAbsolutePaths": "1.0.6",
     "sanitize-html": "2.7.2",

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio