Home Download Docs Code Community
     1	/*
     2	Copyright 2013 The Perkeep Authors
     3	
     4	Licensed under the Apache License, Version 2.0 (the "License");
     5	you may not use this file except in compliance with the License.
     6	You may obtain a copy of the License at
     7	
     8	     http://www.apache.org/licenses/LICENSE-2.0
     9	
    10	Unless required by applicable law or agreed to in writing, software
    11	distributed under the License is distributed on an "AS IS" BASIS,
    12	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13	See the License for the specific language governing permissions and
    14	limitations under the License.
    15	*/
    16	
    17	package importer
    18	
    19	import (
    20		"bytes"
    21		"fmt"
    22		"html/template"
    23		"net/http"
    24		"strings"
    25		"time"
    26	
    27		"perkeep.org/pkg/blob"
    28	)
    29	
    30	func (h *Host) execTemplate(w http.ResponseWriter, r *http.Request, data interface{}) {
    31		tmplName := strings.TrimPrefix(fmt.Sprintf("%T", data), "importer.")
    32		var buf bytes.Buffer
    33		err := h.tmpl.ExecuteTemplate(&buf, tmplName, data)
    34		if err != nil {
    35			http.Error(w, fmt.Sprintf("Error executing template %q: %v", tmplName, err), 500)
    36			return
    37		}
    38		w.Write(buf.Bytes())
    39	}
    40	
    41	type importersRootPage struct {
    42		Title string
    43		Body  importersRootBody
    44	}
    45	
    46	type importersRootBody struct {
    47		Host      *Host
    48		Importers []*importer
    49	}
    50	
    51	type importerPage struct {
    52		Title string
    53		Body  importerBody
    54	}
    55	
    56	type importerBody struct {
    57		Host      *Host
    58		Importer  *importer
    59		SetupHelp template.HTML
    60	}
    61	
    62	type acctPage struct {
    63		Title string
    64		Body  acctBody
    65	}
    66	
    67	type acctBody struct {
    68		Acct       *importerAcct
    69		AcctType   string
    70		Running    bool
    71		LastStatus string
    72		StartedAgo time.Duration // or zero if !Running
    73		LastAgo    time.Duration // non-zero if previous run && !Running
    74		LastError  string
    75	}
    76	
    77	var tmpl = template.Must(template.New("root").Funcs(map[string]interface{}{
    78		"bloblink": func(br blob.Ref) string {
    79			panic("should be overridden; this one won't be called")
    80		},
    81	}).Parse(`
    82	{{define "pageTop"}}
    83	<html>
    84	<head>
    85	   <title>{{.Title}}</title>
    86	</head>
    87	<body>
    88	   <h1>{{.Title}}</h1>
    89	{{end}}
    90	
    91	{{define "pageBottom"}}
    92	</body>
    93	</html>
    94	{{end}}
    95	
    96	
    97	{{define "importersRootPage"}}
    98	  {{template "pageTop" .}}
    99	  {{template "importersRootBody" .Body}}
   100	  {{template "pageBottom"}}
   101	{{end}}
   102	
   103	{{define "importersRootBody"}}
   104	   <ul>
   105	      {{$base := .Host.ImporterBaseURL}}
   106	      {{range .Importers}}
   107	         {{if .TODOIssue}}
   108	             <li><b>{{.Title}}</b>: TODO: <a href="https://perkeep.org/issue/{{.TODOIssue}}">Issue {{.TODOIssue}}</a></li>
   109	         {{else}}
   110	             <li><b><a href="{{$base}}{{.Name}}">{{.Title}}</a></b>{{if .Description}}: {{.Description}}{{end}}</li>
   111	         {{end}}
   112	      {{end}}
   113	   </ul>
   114	{{end}}
   115	
   116	
   117	{{define "importerPage"}}
   118	  {{template "pageTop" .}}
   119	  {{template "importerBody" .Body}}
   120	  {{template "pageBottom"}}
   121	{{end}}
   122	
   123	{{define "importerBody"}}
   124	<p>[<a href="{{.Host.ImporterBaseURL}}">&lt;&lt; Back</a>]</p>
   125	<ul>
   126	  <li>Importer configuration permanode: {{.Importer.Node.PermanodeRef | bloblink}}</li>
   127	  <li>Status: {{.Importer.Status}}</li>
   128	</ul>
   129	
   130	{{if .Importer.ShowClientAuthEditForm}}
   131		{{if .Importer.InsecureForm}}
   132		<h1 style="color:red;">This page is not served securely (no https). Proceed at your own risk.</h1>
   133		{{end}}
   134	    <h1>Client ID &amp; Client Secret</h1>
   135	    <form method='post'>
   136	      <input type='hidden' name="mode" value="saveclientidsecret">
   137	      <table border=0 cellpadding=3>
   138	      <tr><td align=right>Client ID</td><td><input name="clientID" size=50 value="{{.Importer.ClientID}}"></td></tr>
   139	      <tr><td align=right>Client Secret</td><td><input name="clientSecret" type=password size=50 value="{{.Importer.ClientSecret}}"></td></tr>
   140	      <tr><td align=right></td><td><input type='submit' value="Save"></td></tr>
   141	      </table>
   142	    </form>
   143	{{end}}
   144	
   145	{{.SetupHelp}}
   146	
   147	
   148	<h1>Accounts</h1>
   149	<ul>
   150	    {{range .Importer.Accounts}}
   151	       <li><a href="{{.AccountURL}}">{{.AccountLinkText}}</a> {{.AccountLinkSummary}}</li>
   152	    {{end}}
   153	</ul>
   154	{{if .Importer.CanAddNewAccount}}
   155	    <form method='post'>
   156	      <input type='hidden' name="mode" value="newacct">
   157	      <input type='submit' value="Add new account">
   158	    </form>
   159	{{end}}
   160	
   161	{{end}}
   162	
   163	{{define "acctPage"}}
   164	  {{template "pageTop" .}}
   165	  {{template "acctBody" .Body}}
   166	  {{template "pageBottom"}}
   167	{{end}}
   168	
   169	{{define "acctBody"}}
   170	<p>[<a href="./">&lt;&lt; Back</a>]</p>
   171	<ul>
   172	   <li>Account type: {{.AcctType}}</li>
   173	   <li>Account metadata permanode: {{.Acct.AccountObject.PermanodeRef | bloblink}}</li>
   174	   <li>Import root permanode: {{if .Acct.RootObject}}{{.Acct.RootObject.PermanodeRef | bloblink}}{{else}}(none){{end}}</li>
   175	   <li>Configured: {{.Acct.IsAccountReady}}</li>
   176	   <li>Summary: {{.Acct.AccountLinkSummary}}</li>
   177	   <li>Import interval: {{if .Acct.RefreshInterval}}{{.Acct.RefreshInterval}}{{else}}(manual){{end}}</li>
   178	   <li>Running: {{.Running}}</li>
   179	   {{if .Running}}
   180	     <li>Started: {{.StartedAgo}} ago</li>
   181	     <li>Last status: {{.LastStatus}}</li>
   182	   {{else}}
   183	     {{if .LastAgo}}
   184	        <li>Previous run: {{.LastAgo}} ago{{if .LastError}}: {{.LastError}}{{else}} (success){{end}}</li>
   185	     {{end}}
   186	   {{end}}
   187	</ul>
   188	
   189	{{if .Acct.IsAccountReady}}
   190	   <form method='post' style='display: inline'>
   191	   {{if .Running}}
   192	     <input type='hidden' name='mode' value='stop'>
   193	     <input type='submit' value='Pause Import'>
   194	   {{else}}
   195	     <input type='hidden' name='mode' value='start'>
   196	     <input type='submit' value='Start Import'>
   197	   {{end}}
   198	   </form>
   199	{{end}}
   200	
   201	<form method='post' style='display: inline'>
   202	<input type='hidden' name='mode' value='login'>
   203	<input type='submit' value='Re-login'>
   204	</form>
   205	
   206	<form method='post' style='display: inline'>
   207	<input type='hidden' name='mode' value='toggleauto'>
   208	<input type='submit' value='Toggle auto'>
   209	</form>
   210	
   211	<form method='post' style='display: inline'>
   212	<input type='hidden' name='mode' value='delete'>
   213	<input type='submit' value='Delete Account' onclick='return confirm("Delete account?")'>
   214	</form>
   215	
   216	{{end}}
   217	
   218	`))
Website layout inspired by memcached.
Content by the authors.