
<!-- Modal install app -->
<div class="modal fade appstore-install" id="appInstallModal" tabindex="-1" role="dialog">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <img ng-src="{{appInstall.app.iconUrl}}" onerror="this.onerror=null; this.src='img/appicon_fallback.png'" class="app-icon"/>
        <h3 class="appstore-install-title">{{ appInstall.app.manifest.title }}</h3>
        <br/>
        <span class="appstore-install-meta"><a href="{{ appInstall.app.manifest.website }}" target="_blank">{{ appInstall.app.manifest.author }}</a></span>
        <br/>
        <span class="appstore-install-meta">{{ 'appstore.installDialog.lastUpdated' | tr:{ date: (appInstall.app.creationDate | prettyDate) } }}</span>
        <br/>
        <span class="appstore-install-meta">{{ 'appstore.installDialog.memoryRequirement' | tr:{ size: (appInstall.app.manifest.memoryLimit | prettyByteSize:'256 MB') } }}</span>
      </div>
      <div class="modal-body">
        <div class="collapse" id="collapseInstallForm" data-toggle="false">
          <form role="form" name="appInstallForm" ng-submit="appInstall.submit()" autocomplete="off">
            <div class="has-error text-center" ng-show="appInstall.error.other" ng-bind-html="appInstall.error.other"></div>
            <div class="form-group" ng-class="{ 'has-error': (appInstallForm.location.$dirty && appInstallForm.location.$invalid) || (!appInstallForm.location.$dirty && appInstall.error.location) }">
              <label class="control-label" for="appInstallLocationInput">{{ 'appstore.installDialog.location' | tr }}</label>
              <div class="input-group form-inline">
                <input type="text" class="form-control" ng-model="appInstall.location" id="appInstallLocationInput" name="location" placeholder="{{ 'appstore.installDialog.locationPlaceholder' | tr }}" autofocus>
                <div class="input-group-btn">
                  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
                    <span>{{ (appInstall.location ? '.' : '') + appInstall.domain.domain }}</span>
                    <span class="caret"></span>
                  </button>
                  <ul class="dropdown-menu dropdown-menu-right" role="menu">
                    <li ng-repeat="domain in domains">
                      <a href="" ng-click="appInstall.domain = domain">{{ domain.domain }}</a>
                    </li>
                  </ul>
                </div>
              </div>
              <div ng-show="appInstall.error.location" class="text-small">{{ appInstall.error.location }}</div>
            </div>

            <p class="text-small text-warning" ng-show="appInstall.location && appInstall.domain.provider === 'manual'" ng-bind-html="'appstore.installDialog.manualWarning' | tr:{ location: (appInstall.location + '.' + appInstall.domain.domain) }"></p>

            <div class="has-error text-center" ng-show="appInstall.error.port">{{ appInstall.error.port }}</div>
            <div ng-repeat="(env, info) in appInstall.portBindingsInfo">
              <ng-form name="portInfo_form">
                <div class="form-group" ng-class="{ 'has-error': (!appInstallForm.itemName{{$index}}.$dirty && appInstall.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }">
                  <label class="control-label" for="inputPortInfo{{env}}"><input type="checkbox" ng-model="appInstall.portBindingsEnabled[env]">
                    {{ info.title }}
                    <sup>
                      <a popover-placement="top-right" popover-trigger="outsideClick" uib-popover="{{info.description}} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})"><i class="fa fa-question-circle"></i></a>
                    </sup>
                  </label>
                  <input type="number" class="form-control" ng-model="appInstall.portBindings[env]" ng-disabled="!appInstall.portBindingsEnabled[env]" id="inputPortInfo{{env}}" later-name="itemName{{$index}}" min="{{hostPortMin}}" max="{{hostPortMax}}" required>
                </div>
              </ng-form>
            </div>

            <div class="form-group" ng-show="appInstall.app.manifest.addons.email">
              <label class="control-label">{{ 'appstore.installDialog.userManagement' | tr }}</label>
              <p>{{ 'appstore.installDialog.userManagementMailbox' | tr }}
                <span ng-bind-html="'appstore.installDialog.configuredForCloudronEmail' | tr:{ emailDocsLink: 'https://docs.cloudron.io/email/' }">
              </p>
            </div>

            <div class="form-group">
              <label class="control-label" ng-show="!appInstall.customAuth && !appInstall.app.manifest.addons.email">{{ 'appstore.installDialog.userManagement' | tr }} <sup><a ng-href="https://docs.cloudron.io/apps/#access-restriction" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
              <label class="control-label" ng-show="appInstall.customAuth || appInstall.app.manifest.addons.email">{{ 'app.accessControl.userManagement.dashboardVisibility' | tr }} <sup><a ng-href="https://docs.cloudron.io/apps/#dashboard-visibility" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>

              <div class="radio" ng-show="appInstall.optionalSso">
                <label>
                  <input type="radio" ng-model="appInstall.accessRestrictionOption" value="nosso"> {{ 'appstore.installDialog.userManagementLeaveToApp' | tr }}
                </label>
              </div>
              <div class="radio">
                <label>
                  <input type="radio" ng-model="appInstall.accessRestrictionOption" value="any">
                  <span ng-show="!appInstall.customAuth">{{ 'appstore.installDialog.userManagementAllUsers' | tr }}</span>
                  <span ng-show="appInstall.customAuth">{{ 'app.accessControl.userManagement.visibleForAllUsers' | tr }}</span>
                </label>
              </div>
              <div class="radio">
                <label>
                  <input type="radio" ng-model="appInstall.accessRestrictionOption" value="groups">
                  <span ng-show="!appInstall.customAuth">{{ 'appstore.installDialog.userManagementSelectUsers' | tr }}</span>
                  <span ng-show="appInstall.customAuth">{{ 'app.accessControl.userManagement.visibleForSelected' | tr }}</span>
                  <span class="label label-danger" ng-show="appInstall.accessRestrictionOption === 'groups' && !appInstall.isAccessRestrictionValid()">{{ 'appstore.installDialog.errorUserManagementSelectAtLeastOne' | tr }}</span>
                </label>
              </div>
              <div>
                <div style="margin-left: 20px;">
                  <div class="col-md-5">
                    {{ 'appstore.installDialog.users' | tr }}: &nbsp;
                    <multiselect ng-model="appInstall.accessRestriction.users" ng-disabled="appInstall.accessRestrictionOption !== 'groups'" options="user.username for user in users" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
                  </div>

                  <div class="col-md-5">
                    {{ 'appstore.installDialog.groups' | tr }}: &nbsp;
                    <multiselect ng-model="appInstall.accessRestriction.groups" ng-disabled="appInstall.accessRestrictionOption !== 'groups'" options="group.name for group in groups" data-multiple="true" filter-after-rows="5" scroll-after-rows="10"></multiselect>
                  </div>
                </div>
              </div>

              <br/>
              <br/>
            </div>

            <div class="hide">
              <label class="control-label" for="appInstallCertificateInput">Certificate (optional)</label>
              <div class="has-error text-center" ng-show="appInstall.error.cert">{{ appInstall.error.cert }}</div>
              <div class="form-group" ng-class="{ 'has-error': !appInstallForm.certificate.$dirty && appInstall.error.cert }">
                <div class="input-group">
                  <input type="file" id="appInstallCertificateFileInput" style="display:none"/>
                  <input type="text" class="form-control" placeholder="Certificate" ng-model="appInstall.certificateFileName" id="appInstallCertificateInput" name="certificate" onclick="getElementById('appInstallCertificateFileInput').click();" style="cursor: pointer;" ng-required="appInstall.keyFileName">
                  <span class="input-group-addon">
                    <i class="fa fa-upload" onclick="getElementById('appInstallCertificateFileInput').click();"></i>
                  </span>
                </div>
              </div>
              <div class="form-group" ng-class="{ 'has-error': !appInstallForm.key.$dirty && appInstall.error.cert }">
                <div class="input-group">
                  <input type="file" id="appInstallKeyFileInput" style="display:none"/>
                  <input type="text" class="form-control" placeholder="Key" ng-model="appInstall.keyFileName" id="appInstallKeyInput" name="key" onclick="getElementById('appInstallKeyFileInput').click();" style="cursor: pointer;" ng-required="appInstall.certificateFileName">
                  <span class="input-group-addon">
                    <i class="fa fa-upload" onclick="getElementById('appInstallKeyFileInput').click();"></i>
                  </span>
                </div>
              </div>
            </div>

            <input class="ng-hide" type="submit" ng-disabled="(appInstall.accessRestrictionOption === 'groups' && !appInstall.isAccessRestrictionValid()) || !appInstall.accessRestrictionOption || appInstallForm.$invalid || busy"/>
          </form>
        </div>
        <div class="collapse" id="collapseMediaLinksCarousel" data-toggle="false">
          <div ng-repeat="mediaLink in appInstall.mediaLinks" class="slick-item" style="background-image: url('{{mediaLink}}');" ng-show="appInstall.mediaLinks.length == 1"></div>
          <slick init-onload="true" current-index="0" autoplay="true" arrows="false" autoplay-speed="2000" data="appInstall.mediaLinks" ng-show="appInstall.mediaLinks.length > 1">
            <div ng-repeat="mediaLink in appInstall.mediaLinks" class="slick-item" style="background-image: url('{{mediaLink}}');"></div>
          </slick>
          <br/>
          <div class="appstore-install-description">
            <div ng-bind-html="appInstall.app.manifest.description | markdown2html"></div>
          </div>
        </div>
        <div class="collapse" id="collapseResourceConstraint" data-toggle="false">
          <h4 class="text-danger">{{ 'appstore.installDialog.lowOnResources' | tr }}</h4>
          <p>{{ 'appstore.installDialog.pleaseUpgradeServer' | tr }}</p>
        </div>
        <div class="collapse" id="collapseSubscriptionRequired" data-toggle="false">
          <p>{{ 'appstore.installDialog.subscriptionRequired' | tr }}</p>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-success pull-left" ng-click="openSubscriptionSetup()" ng-show="appInstall.state === 'subscriptionRequired'">{{ 'appstore.installDialog.setupSubscriptionAction' | tr }}</button>
        <button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
        <button type="button" class="btn btn-danger" ng-show="appInstall.state === 'resourceConstraint'" ng-click="appInstall.showForm(true)">{{ 'appstore.installDialog.installAnywayAction' | tr }}</button>
        <button type="button" class="btn btn-success" ng-show="appInstall.state === 'appInfo'" ng-click="appInstall.showForm()">{{ 'appstore.installDialog.installAction' | tr }}</button>
        <button type="button" class="btn btn-success" ng-show="appInstall.state === 'installForm'" ng-click="appInstall.submit()" ng-disabled="(appInstall.accessRestrictionOption === 'groups' && !appInstall.isAccessRestrictionValid()) || !appInstall.accessRestrictionOption || appInstallForm.$invalid || appInstall.busy"><i class="fa fa-circle-notch fa-spin" ng-show="appInstall.busy"></i> {{ 'appstore.installDialog.doInstallAction' | tr:{ dnsOverwrite: appInstall.needsOverwrite } }}</button>
      </div>
    </div>
  </div>
</div>

<!-- Modal app not found -->
<div class="modal fade" id="appNotFoundModal" tabindex="-1" role="dialog">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">{{ 'appstore.appNotFoundDialog.title' | tr }}</h4>
      </div>
      <div class="modal-body" ng-bind-html="'appstore.appNotFoundDialog.description' | tr:{ appId: appNotFound.appId, version: appNotFound.version }"></div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary" data-dismiss="modal">{{ 'main.dialog.close' | tr }}</button>
      </div>
    </div>
  </div>
</div>

<div ng-show="!ready" class="loading-banner">
  <h1><i class="fa fa-circle-notch fa-spin"></i></h1>
</div>

<!-- appstore login -->
<div ng-show="ready && !validSubscription" class="container card card-small appstore-login ng-cloak">
  <div class="col-md-12 text-center">
    <h1 ng-show="appstoreLogin.register">{{ 'appstore.accountDialog.titleSignUp' | tr }}</h1>
    <h1 ng-hide="appstoreLogin.register">{{ 'appstore.accountDialog.titleLogin' | tr }}</h1>
  </div>
  <div class="col-md-12 text-center">
    <p>{{ 'appstore.accountDialog.description' | tr }}</p>
  </div>
  <div class="col-md-12" style="margin-bottom: 10px;">
    <small class="text-danger" ng-show="appstoreLogin.error.generic">{{ appstoreLogin.error.generic }}</small>
  </div>
  <div class="col-md-12">
    <br/>

    <form name="appstoreLoginForm" role="form" novalidate ng-submit="appstoreLogin.submit()" autocomplete="off">
      <input type="password" style="display: none;">

      <div class="form-group" ng-class="{ 'has-error': (appstoreLoginForm.email.$dirty && appstoreLoginForm.email.$invalid) || appstoreLogin.error.generic }">
          <label class="control-label">{{ 'appstore.accountDialog.email' | tr }}</label>
          <input type="email" class="form-control" ng-model="appstoreLogin.email" id="inputAppstoreLoginEmail" name="email" required autofocus>
          <div class="control-label" ng-show="(!appstoreLoginForm.email.$dirty && appstoreLogin.error.email) || (appstoreLoginForm.email.$dirty && appstoreLoginForm.email.$invalid) || appstoreLogin.error.email">
              <small class="text-danger" ng-show="appstoreLogin.error.email">{{ appstoreLogin.error.email }}</small>
          </div>
      </div>

      <div class="form-group" ng-class="{ 'has-error': (!appstoreLoginForm.password.$dirty && appstoreLogin.error.password) || (appstoreLoginForm.password.$dirty && appstoreLoginForm.password.$invalid) || appstoreLogin.error.generic }">
          <label class="control-label">{{ 'appstore.accountDialog.password' | tr }}</label>
          <input type="password" class="form-control" ng-model="appstoreLogin.password" id="inputAppstoreLoginPassword" name="password" required>
          <div class="control-label" ng-show="(!appstoreLoginForm.password.$dirty && appstoreLogin.error.password) || (appstoreLoginForm.password.$dirty && appstoreLoginForm.password.$invalid)">
              <small ng-show="!appstoreLoginForm.password.$dirty && appstoreLogin.error.password">{{ 'appstore.accountDialog.errorWrongPassword' | tr }}</small>
          </div>
      </div>

      <div class="form-group" ng-hide="appstoreLogin.register" ng-class="{ 'has-error': appstoreLogin.error.totpToken }">
          <label class="control-label">{{ 'appstore.accountDialog.2faToken' | tr }}</label>
          <input type="text" class="form-control" ng-model="appstoreLogin.totpToken" id="inputAppstoreLoginTotpToken" name="totpToken">
          <div class="control-label" ng-show="appstoreLogin.error.totpToken">
              <small ng-show="appstoreLogin.error.totpToken">{{ appstoreLogin.error.totpToken }}</small>
          </div>
      </div>

      <div class="form-group">
        <label class="control-label">{{ 'appstore.accountDialog.intendedUse' | tr }}</label>
        <select class="purpose form-control" ng-model="appstoreLogin.purpose" required>
          <option value="" disabled selected hidden>{{ 'appstore.accountDialog.chooseAnOption' | tr }}</option>
          <option value="personal_cloud">Personal use</option>
          <option value="business_cloud">Business use</option>
          <option value="website_hosting">Website hosting</option>
          <option value="msp">Managed Service Provider</option>
          <option value="paas">PaaS - Develop &amp; deploy apps</option>
          <option value="single_app">Host only one app</option>
          <option value="exploring">Just exploring</option>
        </select>
      </div>

      <div class="checkbox">
        <label>
          <input type="checkbox" ng-model="appstoreLogin.termsAccepted"><span ng-bind-html="'appstore.accountDialog.licenseCheckbox' | tr:{ licenseLink: 'https://cloudron.io/legal/license.html' }"></span>
        </label>
      </div>

      <br/>

      <center>
        <button type="submit" class="btn btn-lg btn-success" ng-disabled="appstoreLoginForm.$invalid || appstoreLogin.busy || !appstoreLogin.termsAccepted">
          <i class="fa fa-circle-notch fa-spin" ng-show="appstoreLogin.busy"></i> <span ng-hide="appstoreLogin.register">{{ 'appstore.accountDialog.loginAction' | tr }}</span><span ng-show="appstoreLogin.register">{{ 'appstore.accountDialog.createAccountAction' | tr }}</span>
        </button>

        <br/>
        <br/>

        <a href="" ng-click="appstoreLogin.register = true" ng-hide="appstoreLogin.register">{{ 'appstore.accountDialog.switchToSignUpAction' | tr }}</a>
        <a href="" ng-click="appstoreLogin.register = false" ng-show="appstoreLogin.register">{{ 'appstore.accountDialog.switchToLoginAction' | tr }}</a>
      </center>

    </form>
  </div>
</div>

<!-- give more vertical spacing so the login form does not appear clipped -->
<div ng-show="ready && !validSubscription">
  <br/>
  <br/>
</div>

<div ng-show="ready && validSubscription" class="ng-cloak appstore-toolbar">
  <div class="appstore-toolbar-content">
    <button class="btn" type="button" ng-click="showCategory('');" ng-class="{ 'btn-primary': '' === category }">{{ 'appstore.category.all' | tr }}</button>
    <button class="btn" type="button" ng-click="showCategory('new');" ng-class="{ 'btn-primary': 'new' === category }">{{ 'appstore.category.newApps' | tr }}</button>
    <div class="dropdown">
      <button class="btn dropdown-toggle" type="button" data-toggle="dropdown" ng-class="{ 'btn-primary': '' !== category && 'recent' !== category && 'new' !== category }">
        {{ categoryButtonLabel(category) }}
        <span class="caret"></span>
      </button>
      <ul class="dropdown-menu">
        <li ng-repeat="category in categories"><a href="" ng-click="showCategory(category.id);"><i class="{{ category.icon }} fa-fw"></i> {{ category.label }}</a></li>
      </ul>
    </div>
    <input type="text" id="appstoreSearch" class="form-control" placeholder="{{ 'appstore.searchPlaceholder' | tr }}" ng-model="searchString" ng-change="search()" autofocus>
  </div>
</div>

<div ng-show="ready && validSubscription" class="ng-cloak appstore-grid">
  <div class="row">
    <div class="col-md-12 text-center" ng-hide="apps.length">
      <br/>
      <br/>
      <br/>
      <h3 class="text-muted">{{ 'appstore.noAppsFound' | tr }}</h3>
      <br/>
      <a href="https://forum.cloudron.io/category/5/app-requests" target="_blank">{{ 'appstore.appMissing' | tr }}</a>
    </div>
    <div class="col-md-12" ng-show="category === '' && popularApps.length">
      <div class="row-no-margin">
        <div class="col-sm-12">
          <h2>{{ 'appstore.category.popular' | tr }}</h2>
        </div>
      </div>
      <div class="row-no-margin">
        <div class="col-sm-1 appstore-item" ng-repeat="app in popularApps">
          <div class="appstore-item-content highlight" ng-click="gotoApp(app)" ng-class="{ 'appstore-item-content-testing': app.releaseState === 'unstable' }">
            <span class="badge badge-danger appstore-item-badge-testing" ng-show="app.releaseState === 'unstable'">{{ 'appstore.unstable' | tr }}</span>
            <div class="appstore-item-content-icon col-same-height">
              <img ng-src="{{app.iconUrl}}" onerror="this.onerror=null;this.src='img/appicon_fallback.png'" class="app-icon"/>
            </div>
            <div class="appstore-item-content-description col-same-height">
              <h4 class="appstore-item-content-title">{{ app.manifest.title }}</h4>
              <div class="appstore-item-content-tagline text-muted">{{ app.manifest.tagline }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="col-md-12" ng-show="apps.length">
      <div class="row-no-margin" ng-show="!category && !searchString">
        <div class="col-sm-12">
          <h2>{{ 'appstore.category.all' | tr }}</h2>
        </div>
      </div>
      <div class="row-no-margin">
        <div class="col-sm-1 appstore-item" ng-repeat="app in apps">
          <div class="appstore-item-content highlight" ng-click="gotoApp(app)" ng-class="{ 'appstore-item-content-testing': app.releaseState === 'unstable' }">
            <span class="badge badge-danger appstore-item-badge-testing" ng-show="app.releaseState === 'unstable'">{{ 'appstore.unstable' | tr }}</span>
            <div class="appstore-item-content-icon col-same-height">
              <img ng-src="{{app.iconUrl}}" onerror="this.onerror=null;this.src='img/appicon_fallback.png'" class="app-icon"/>
            </div>
            <div class="appstore-item-content-description col-same-height">
              <h4 class="appstore-item-content-title">{{ app.manifest.title }}</h4>
              <div class="appstore-item-content-tagline text-muted">{{ app.manifest.tagline }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
