~sircmpwn/names.sr.ht

b317fe99180873fd98c021df4ca6ebb4178f050d — Drew DeVault 1 year, 9 months ago 7d85145
Mock up contact list and new contact pages

Still not sure where to put the new contact button.
M names/app.py => names/app.py +2 -0
@@ 13,8 13,10 @@ class NamesApp(SrhtFlask):

        self.url_map.strict_slashes = False

        from names.blueprints.contacts import contacts
        from names.blueprints.web import web

        self.register_blueprint(contacts)
        self.register_blueprint(web)

app = NamesApp()

A names/blueprints/contacts.py => names/blueprints/contacts.py +14 -0
@@ 0,0 1,14 @@
from flask import Blueprint, render_template
from srht.oauth import loginrequired

contacts = Blueprint("names.contacts", __name__)

@contacts.route("/contacts")
@loginrequired
def contacts_GET():
    return render_template("contacts.html")

@contacts.route("/contacts/new")
@loginrequired
def new_GET():
    return render_template("new-contact.html")

M names/blueprints/web.py => names/blueprints/web.py +1 -3
@@ 1,13 1,11 @@
import re
from flask import Blueprint, render_template, request, redirect, url_for, abort
from flask_login import current_user
from jinja2 import Markup
from names.pygments import ZoneLexer
from names.types import User
from pygments import highlight
from pygments.formatters import HtmlFormatter
from srht.flask import loginrequired
from srht.oauth import UserType
from srht.oauth import current_user, loginrequired, UserType
from srht.validation import Validation

# TODO: Make OpenSRS integration optional

A names/templates/contacts.html => names/templates/contacts.html +168 -0
@@ 0,0 1,168 @@
{% extends "layout.html" %}
{% block content %}
<div class="row">
  <div class="col-md-8">
    <h3>Manage contacts</h3>
    <div class="event-list" style="margin-top: 0.5rem">
      <div class="event">
        <h4>
          John Doe &mdash; Acme, Inc
          <small class="text-muted pull-right">
            b20968c6-8b99-42a0-8d80-da35eb4d945c
          </small>
        </h4>
        <address class="contact row">
          <dl class="col-md-6">
            <dt>Address</dt>
            <dd>
              123 Main St.<br />
              Suite 1337<br />
              Philadephia, PA 19102<br />
              United States
            </dd>
          </dl>
          <dl class="col-md-6">
            <dd><a href="#">jdoe@example.org</a></dd>
            <dt>Phone</dt>
            <dd>+1 (201) 123-4321</dd>
            <dt>Fax</dt>
            <dd>+1 (201) 123-4321 x222</dd>
          </dl>
        </address>
        <div class="row" style="margin-bottom: 1rem">
          <dl class="col-md-12">
            <dt>Notes</dt>
            <dd>
              This is the contact used for most domains we manage on behalf of
              Acme, Inc. The customer has asked not to update it without a
              request in writing, for security reasons.
            </dd>
          </dl>
        </div>
        <div class="row">
          <div class="col-md-3 offset-md-9">
            <button class="btn btn-block btn-default">
              Edit {{icon("caret-right")}}
            </button>
          </div>
        </div>
      </div>
      <div class="event">
        <h4>
          Jane Doe &mdash; Acme, Inc
          <small class="text-muted pull-right">
            b20968c6-8b99-42a0-8d80-da35eb4d945c
          </small>
        </h4>
        <address class="contact row">
          <dl class="col-md-6">
            <dt>Address</dt>
            <dd>
              123 Main St.<br />
              Suite 1337<br />
              Philadephia, PA 19102<br />
              United States
            </dd>
          </dl>
          <dl class="col-md-6">
            <dd><a href="#">jdoe@example.org</a></dd>
            <dt>Phone</dt>
            <dd>+1 (201) 123-4321</dd>
            <dt>Fax</dt>
            <dd>+1 (201) 123-4321 x222</dd>
          </dl>
        </address>
        <div class="row">
          <div class="col-md-3 offset-md-9">
            <button class="btn btn-block btn-default">
              Edit {{icon("caret-right")}}
            </button>
          </div>
        </div>
      </div>
    </div>
    <h3>Top-level domain specific</h3>
    <div class="event-list">
      <div class="event contact">
        <h4>
          .aero
          <small class="text-muted pull-right">
            b20968c6-8b99-42a0-8d80-da35eb4d945c
          </small>
        </h4>
        <blockquote class="text-muted">
          <p>
            Registration of .AERO domains is restricted to members of the
            aviation community such as airlines, airports, and qualifying
            companies and individuals.
          </p>
          <p>
            To prove that they meet the requirements, registrants must provide
            an Eligibility and Name Selection (ENS) ID and password, which can
            be obtained by applying to the registry through
            <a href="#">nic.aero</a>.
          </p>
        </blockquote>
        <dl>
          <dt>Eligibility and Name Selection (ENS) identifier</dt>
          <dd>123-321-123</dd>
          <dt>Eligibility and Name Selection (ENS) password</dt>
          <dd><span class="text-muted">[hidden]</span></dd>
        </dl>
        <div class="row">
          <div class="col-md-3 offset-md-9">
            <button class="btn btn-block btn-default">
              Edit {{icon("caret-right")}}
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="col-md-4">
    <h3>Default contacts</h3>
    <div class="event-list">
      <div class="event">
        <h4>Owner Contact</h4>
        John Doe &mdash; Acme, Inc<br />
        <a href="#">jdoe@example.org</a><br />
        <span class="text-muted">
          b20968c6-8b99-42a0...
        </span>
        <a href="#">{{icon("external-link-alt")}}</a>
      </div>
      <div class="event">
        <h4>Administrative Contact</h4>
        Jane Doe &mdash; Acme, Inc<br />
        <a href="#">jdoe@example.org</a><br />
        <span class="text-muted">
          b20968c6-8b99-42a0...
        </span>
        <a href="#">{{icon("external-link-alt")}}</a>
      </div>
      <div class="event">
        <h4>Billing Contact</h4>
        John Doe &mdash; Acme, Inc<br />
        <a href="#">jdoe@example.org</a><br />
        <span class="text-muted">
          b20968c6-8b99-42a0...
        </span>
        <a href="#">{{icon("external-link-alt")}}</a>
      </div>
      <div class="event">
        <h4>Technical Contact</h4>
        Jane Doe &mdash; Acme, Inc<br />
        <a href="#">jdoe@example.org</a><br />
        <span class="text-muted">
          b20968c6-8b99-42a0...
        </span>
        <a href="#">{{icon("external-link-alt")}}</a>
      </div>
    </div>
    <a
      href="{{url_for("names.contacts.new_GET")}}"
      class="btn btn-primary btn-block"
    >Add a new contact {{icon("caret-right")}}</a>
  </div>
</div>
{% endblock %}

M names/templates/dashboard.html => names/templates/dashboard.html +8 -6
@@ 8,12 8,14 @@
      service. Documentation for its use is
      <a href="https://man.sr.ht/names.sr.ht">available here</a>.
    </p>
    <a href="{{url_for('.create_GET')}}" class="btn btn-primary btn-block">
      Add a domain {{icon("caret-right")}}
    </a>
    <a href="#" class="btn btn-default btn-block">
      Manage contacts {{icon("caret-right")}}
    </a>
    <a
      href="{{url_for('names.web.create_GET')}}"
      class="btn btn-primary btn-block"
    >Add a domain {{icon("caret-right")}}</a>
    <a
      href="{{url_for('names.contacts.contacts_GET')}}"
      class="btn btn-default btn-block"
    >Manage contacts {{icon("caret-right")}}</a>
  </div>
  <div class="col-md-8">
    <div class="alert alert-info">

A names/templates/new-contact.html => names/templates/new-contact.html +270 -0
@@ 0,0 1,270 @@
{% extends "layout.html" %}
{% block content %}
<div class="row">
  <div class="col-md-12">
    <h3>Add a new contact</h3>
    <p>
      This contact information is required by ICANN to be accurate and kept
      up-to-date. This information will be made public. To learn more,
      consult the <a
        href="https://www.icann.org/resources/pages/registrant-contact-information-wdrp-2017-08-31-en"
        rel="nofollow noopener"
        target="_blank"
      >ICANN Knowledge Base</a>. If the geographic demonyms listed here are not
      appropriate for your location, use the closest approximation which is
      appropriate for you.
    </p>
  </div>
</div>
{# TODO: Add validation messages for all fields #}
<form method="POST">
  {{csrf_token()}}
  <div class="row">
    <div class="col-md-4 offset-md-2 form-group">
      <label for="first_name">First Name</label>
      <input
        type="text"
        id="first_name"
        name="first_name"
        class="form-control {{valid.cls("first_name")}}"
        placeholder="First name"
        maxlength="64"
        required
        value="{{first_name or ""}}" />
      {{valid.summary("first_name")}}
    </div>
    <div class="col-md-4 form-group">
      <label for="last_name">Last Name</label>
      <input
        type="text"
        id="last_name"
        name="last_name"
        class="form-control {{valid.cls("last_name")}}"
        placeholder="Last name"
        maxlength="64"
        required
        value="{{last_name or ""}}" />
    </div>
    <div class="col-md-8 offset-md-2 form-group">
      <label for="org_name">Organization Name</label>
      <input
        type="text"
        id="org_name"
        name="org_name"
        class="form-control {{valid.cls("org_name")}}"
        placeholder="Organization name"
        maxlength="64"
        required
        value="{{org_name or ""}}" />
    </div>
    <div class="col-md-8 offset-md-2 form-group">
      <label for="email">Email address</label>
      <input
        type="text"
        id="email"
        name="email"
        class="form-control {{valid.cls("email")}}"
        placeholder="Email address"
        maxlength="128"
        required
        value="{{post_code or current_user.email}}" />
    </div>
    <div class="col-md-8 offset-md-2 form-group">
      <label for="address_1">Address</label>
      <input
        type="text"
        id="address_1"
        name="address_1"
        class="form-control {{valid.cls("address_1")}}"
        placeholder="Address"
        maxlength="64"
        required
        value="{{address_1 or ""}}" />
    </div>
    <div class="col-md-8 offset-md-2 form-group">
      <input
        type="text"
        id="address_2"
        name="address_2"
        class="form-control {{valid.cls("address_2")}}"
        placeholder="Address (continued, optional)"
        maxlength="64"
        value="{{address_2 or ""}}" />
    </div>
    <div class="col-md-8 offset-md-2 form-group">
      <input
        type="text"
        id="address_3"
        name="address_3"
        class="form-control {{valid.cls("address_3")}}"
        placeholder="Address (continued, optional)"
        maxlength="64"
        value="{{address_3 or ""}}" />
    </div>
    <div class="col-md-4 offset-md-2 form-group">
      <label for="city">City</label>
      <input
        type="text"
        id="city"
        name="city"
        class="form-control {{valid.cls("city")}}"
        placeholder="City"
        maxlength="64"
        required
        value="{{city or ""}}" />
    </div>
    <div class="col-md-4 form-group">
      <label for="state">State or Province</label>
      <input
        type="text"
        id="state"
        name="state"
        class="form-control {{valid.cls("state")}}"
        placeholder="State or Province"
        maxlength="32"
        value="{{state or ""}}" />
    </div>
    <div class="col-md-4 offset-md-2 form-group">
      <label for="post_code">Post code</label>
      <input
        type="text"
        id="post_code"
        name="post_code"
        class="form-control {{valid.cls("post_code")}}"
        placeholder="Post code or zip code"
        maxlength="16"
        required
        value="{{post_code or ""}}" />
    </div>
    <div class="col-md-4 form-group">
      <label for="country">Country</label>
      {# TODO: Populate dropdown #}
      <select
        name="country"
        id="country"
        class="form-control {{valid.cls("country")}}"
        placeholder="Country"
        required
      >
        <option value="US">United States of America</option>
      </select>
    </div>
    <div class="col-md-4 offset-md-2 form-group">
      <label for="phone">Phone number</label>
      <input
        type="tel"
        id="phone"
        name="phone"
        class="form-control {{valid.cls("phone")}}"
        placeholder="+1 (123) 123-1234"
        maxlength="32"
        value="{{phone or ""}}" />
    </div>
    <div class="col-md-4 form-group">
      <label for="fax">Fax number</label>
      <input
        type="tel"
        id="fax"
        name="fax"
        class="form-control {{valid.cls("fax")}}"
        placeholder="+1 (123) 123-1234 (optional)"
        maxlength="32"
        value="{{fax or ""}}" />
    </div>
  </div>
  <div class="row">
    <details class="extra-details col-md-8 offset-md-2">
      <summary>
        Add optional information (required for some top-level domains)
      </summary>
      <div class="row">
        <div class="col-md-6">
          <div class="form-group">
            {# TODO: Dropdown #}
            <label for="text">Language preference</label>
            <input
              type="text"
              id="language"
              name="language"
              class="form-control {{valid.cls("language")}}"
              placeholder="Language preference"
              maxlength="32"
              value="{{language or ""}}" />
          </div>
        </div>
        <div class="col-md-6">
          <div class="form-group">
            <label for="text">VAT number</label>
            <input
              type="text"
              id="vat"
              name="vat"
              class="form-control {{valid.cls("vat")}}"
              placeholder="Value-Added Tax number"
              maxlength="16"
              value="{{vat or ""}}" />
          </div>
        </div>
      </div>
    </details>
  </div>
  <div class="row">
    <div class="col-md-8 offset-md-2" style="margin-bottom: 1rem">
      <h5>Use this contact as the default:</h5>
      <div class="form-check form-check-inline">
        <input
          class="form-check-input"
          type="checkbox"
          name="use_owner"
          id="use_owner" />
        <label class="form-check-label" for="use_owner">
          Owner contact
        </label>
      </div>
      <div class="form-check form-check-inline">
        <input
          class="form-check-input"
          type="checkbox"
          name="use_admin"
          id="use_admin" />
        <label class="form-check-label" for="use_admin">
          Administrative contact
        </label>
      </div>
      <div class="form-check form-check-inline">
        <input
          class="form-check-input"
          type="checkbox"
          name="use_billing"
          id="use_billing" />
        <label class="form-check-label" for="use_billing">
          Billing contact
        </label>
      </div>
      <div class="form-check form-check-inline">
        <input
          class="form-check-input"
          type="checkbox"
          name="use_tech"
          id="use_tech" />
        <label class="form-check-label" for="use_tech">
          Technical contact
        </label>
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-md-2 offset-md-6">
      <a
        href="{{url_for("names.contacts.contacts_GET")}}"
        class="btn btn-block btn-default"
      >Cancel</a>
    </div>
    <div class="col-md-2">
      <button type="submit" class="btn btn-block btn-primary">
        Submit {{icon("caret-right")}}
      </button>
    </div>
  </div>
</form>
{% endblock %}

M scss/main.scss => scss/main.scss +32 -0
@@ 1,1 1,33 @@
@import "base";

.contact {
  margin-top: 1rem;

  dl, dd {
    margin-bottom: 0;
  }

  blockquote {
    margin-top: 0.5rem;
  }
}

h4 small {
  line-height: 1.65;
}

.extra-details {
  margin-bottom: 1rem;

  &:not([open]) summary {
    @extend .text-muted;
  }

  &[open] {
    background: #eee;

    summary {
      margin-bottom: 0.5rem;
    }
  }
}