Страница входа в СПА в Полимере - PullRequest
0 голосов
/ 22 октября 2018

Я довольно новичок в Polymer и использую шаблон Polymer 2.0 Starter Kit для всех своих приложений.Большинство моих приложений очень похожи - страница входа, которая перенаправляет вас на разные порталы в зависимости от роли пользователя (обычно администратора или пользователя).Порталы имеют app-drawer с различными настройками представлений через iron-pages.

Мой текущий поток дублирует шаблон my-app в каждом «портале».Я просто не уверен, что это правильный способ сделать это.Я объясню дальше.

Использование my-app как есть из начального набора с железными страницами для загрузки login-view, admin-portal и пользовательского портала, по умолчанию login-view.

После того, как пользователь вошел в систему, приложение загрузит admin-portal или user-portal в зависимости от того, какой пользователь вошел в систему.

И admin-portal, и user-portal имеют структуру, очень похожую наmy-app, с app-drawer, а затем iron-pages загрузками просмотров, специфичными для возможностей администратора или пользовательских возможностей.В основном мне было интересно, является ли это наилучшей практикой - у вас всегда есть вложенный iron-pages.Есть ли что-то, чтобы абстрагироваться от login-view?

Код:

my-app - готовый шаблон

<app-location
    route="{{route}}"
    url-space-regex="^[[rootPath]]">
</app-location>

<app-route
    route="{{route}}"
    pattern="[[rootPath]]:page"
    data="{{routeData}}"
    tail="{{subroute}}">
</app-route>

<iron-pages
    selected="[[page]]"
    attr-for-selected="name"
    fallback-selection="view404"
    role="main">
  <login-view name="login" current-user="{{currentUser}}"></login-view>
  <superuser-portal name="superuser"></superuser-portal>
  <admin-portal name="admin" current-user="{{currentUser}}"></admin-portal>
  <doctor-portal name="doctor" current-user="{{currentUser}}"></doctor-portal>
  <my-view404 name="view404"></my-view404>
</iron-pages>

  _routePageChanged(page) {
    //console.log(this.user.email);
    // If no page was found in the route data, page will be an empty string.
    // Default to 'view1' in that case.
    this.page = page || 'login';
  }

  _pageChanged(page) {
    console.log('_pageChanged: ' + page);

    let resolvedPageUrl = this.resolveUrl('my-' + page + '.html');

    if(page === 'login') {
      resolvedPageUrl = this.resolveUrl('login-view.html');
    } else if(page === 'superuser') {
      resolvedPageUrl = this.resolveUrl('superuser-portal.html');
    } else if(page === 'admin') {
      resolvedPageUrl = this.resolveUrl('admin-portal.html');
    } else if(page === 'doctor') {
      resolvedPageUrl = this.resolveUrl('doctor-portal.html');
    }

    console.log('resolvedPageUrl: ' + resolvedPageUrl);

    Polymer.importHref(
        resolvedPageUrl,
        null,
        this._showPage404.bind(this),
        true);
  }

admin-portal - опять же, в основном, как и в готовом шаблоне

    <app-route route="{{route}}" pattern="/admin/:page" data="{{routeData}}" tail="{{subroute}}">
    </app-route>

    <!-- <firebase-auth id="auth" user="{{user}}" on-error="handleError"></firebase-auth> -->

    <app-drawer-layout fullbleed narrow="{{narrow}}">
      <app-drawer id="drawer" slot="drawer" swipe-open="[[narrow]]">
        <div class="drawerHeader">
          <div class="drawerTitle">GetonHealth</div>
          <div class="drawerSubtitle">[[displayName]]</div>
        </div>
        <div style="margin-top: 24px; color: white;">
          <vaadin-list-box>
            <iron-selector attr-for-selected="name" selected="{{routeData.page}}">
              <vaadin-item name="calendar">
                <iron-icon icon="vaadin:calendar"></iron-icon>
                Calendar
              </vaadin-item>
              <vaadin-item name="doctors">
                <iron-icon icon="vaadin:specialist"></iron-icon>
                Manage Doctors
              </vaadin-item>
              <vaadin-item name="view3">
                <iron-icon icon="vaadin:cog-o"></iron-icon>
                Settings
              </vaadin-item>
              <vaadin-item name="view4">
                <iron-icon icon="vaadin:info-circle-o"></iron-icon>
                Help
              </vaadin-item>
              <vaadin-item name="logout">
                <iron-icon icon="vaadin:exit-o"></iron-icon>
                Sign Out
              </vaadin-item>
            </iron-selector>
          </vaadin-list-box>
        </div>
      </app-drawer>
      <app-header-layout>
        <app-header>
          <app-toolbar effects="waterfall">
            <paper-icon-button icon="my-icons:menu" drawer-toggle=""></paper-icon-button>
            <div class="main-title" main-title>[[pageTitle]]</div>
          </app-toolbar>
        </app-header>

        <iron-pages selected="[[page]]" attr-for-selected="name" fallback-selection="view404" role="main">
          <admin-dashboard name="dashboard"></admin-dashboard>
          <admin-manage-doctors name="doctors"></admin-manage-doctors>
          <manage-doctor-detail name="doctor" page-title="{{pageTitle}}"></manage-doctor-detail>
          <admin-calendar-view name="calendar" narrow="[[narrow]]"></admin-calendar-view>
          <admin-new-event name="newevent"></admin-new-event>
          <admin-event-detail name="event" page-title="{{pageTitle}}"></admin-event-detail>
          <admin-reschedule-view name="reschedule" page-title="{{pageTitle}}"></admin-reschedule-view>
          <admin-new-appointment name="newappointment" current-user="{{currentUser}}"></admin-new-appointment>
          <my-view404 name="view404"></my-view404>
        </iron-pages>

      </app-header-layout>
    </app-drawer-layout>

  </template>

  <script>
    class AdminPortal extends Polymer.Element {
      static get is() { return 'admin-portal'; }

      static get properties() {
        return {
          pageTitle: String,
          displayName: String,
          currentUser: {
            type: Object,
            value: {}
          },
          page: {
            type: String,
            reflectToAttribute: true,
            observer: '_pageChanged',
          },
          routeData: Object,
          subroute: Object,
        };
      }

      static get observers() {
        return [
          '_routePageChanged(routeData.page)',
        ];
      }

      _routePageChanged(page) {
        // If no page was found in the route data, page will be an empty string.
        // Default to 'view1' in that case.
        this.page = page || 'calendar';
      }

      _pageChanged(page) {
        console.log('_pageChanged: ' + page);

        let resolvedPageUrl = this.resolveUrl('my-' + page + '.html');

        if (page === 'dashboard') {
          this.set('pageTitle', 'Dashboard');
          resolvedPageUrl = this.resolveUrl('admin/views/admin-dashboard.html');
        } else if (page === 'doctors') {
          this.set('pageTitle', 'Manage doctors');
          resolvedPageUrl = this.resolveUrl('admin/views/admin-manage-doctors.html');
        } else if (page === 'doctor') {
          this.set('pageTitle', '');
          resolvedPageUrl = this.resolveUrl('admin/views/manage-doctor-detail.html');
        } else if (page === 'calendar') {
          this.set('pageTitle', 'Calendar');
          this.set('queryParams', {});
          resolvedPageUrl = this.resolveUrl('admin/views/admin-calendar-view.html');
        } else if (page === 'newevent') {
          this.set('pageTitle', 'Create new event');
          resolvedPageUrl = this.resolveUrl('admin/views/admin-new-event.html');
        } else if (page === 'event') {
          resolvedPageUrl = this.resolveUrl('admin/views/admin-event-detail-test.html');
        } else if (page === 'newappointment') {
          resolvedPageUrl = this.resolveUrl('admin/views/admin-new-appointment.html');
        } else if (page === 'reschedule') {
          resolvedPageUrl = this.resolveUrl('admin/views/admin-reschedule-view.html');
        } else if (page === 'logout') {
          this.logout();
          return;
        }

        Polymer.importHref(
          resolvedPageUrl,
          null,
          this._showPage404.bind(this),
          true);

        if (!this.$.drawer.persistent) {
          this.$.drawer.close();
        }
      }

login-view

performLogin() {
    this.$.auth.signInWithEmailAndPassword(this.username, this.password)
      .then(response => {
        this.username = '';
        this.password = '';
        this.getUserFromFirestore(response);
      }).catch(error => {
        console.error(error);
        this.$.inputPassword.invalid = true;
        this.$.inputPassword.errorMessage = error.message;
        this.$.inputPassword.validate();
      });
  }

  getUserFromFirestore(user) {
    firestore.collection('users').doc(user.uid)
      .get()
      .then(doc => {
        console.log(doc.data());
        //this.set('currentUser', this.docToObject(doc));
        this.changePage(user.uid, doc.data().role);
      })
      .catch(error => {
        console.error(error);
      });
  }

  changePage(uid, role) {

    let page = '';

    if (role === 'superuser') {
      page = '/superuser/dashboard';
    } else if (role === 'admin') {
      page = '/admin/calendar';
    } else if (role === 'doctor') {
      page = '/doctor/clinics';
    }

    setTimeout(() => {
      window.history.pushState({}, null, page);
      window.dispatchEvent(new CustomEvent('location-changed'));
    }, 1000);
  }

1 Ответ

0 голосов
/ 22 октября 2018

Ничто не кажется особенно неправильным с этой реализацией, и это кажется простым.Логин, имеющий собственный вид, тоже подойдет.С ним связан отображаемый DOM («Пожалуйста, войдите в систему», имя пользователя, поле пароля), поэтому нет ничего плохого в том, чтобы иметь его в качестве выбираемого представления со знанием аутентификации внутри него.

Просто убедитесь, что логинСтраница не является привратником значимых действий.То есть пользователь не может добавлять / удалять данные из магазина, просто меняя страницы в инспекторе.iron-pages! == безопасность, только навигация.

Кроме того, использование вложенных iron-pages не является лучшей практикой.iron-pages по существу является прославленным element.setAttribute('hidden', '') и element.removeAttribute('hidden').Тем не менее, общая ошибка с вложенным iron-pages заключается в отслеживании состояния выхода при переходе в родительском iron-pages.например, логин переходит к админу, затем в админ вы переходите к перепланированию, затем вы авторизуетесь как другой админ, портал администратора, вероятно, не должен автоматически перепланировать.

...