Add slug and upload dest to settings (#2)
This commit is contained in:
		
							parent
							
								
									1d096d696b
								
							
						
					
					
						commit
						355ade8c87
					
				@ -888,12 +888,14 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
 | 
				
			|||||||
                    get webLog.id
 | 
					                    get webLog.id
 | 
				
			||||||
                    update [
 | 
					                    update [
 | 
				
			||||||
                        "name",         webLog.name :> obj
 | 
					                        "name",         webLog.name :> obj
 | 
				
			||||||
 | 
					                        "slug",         webLog.slug
 | 
				
			||||||
                        "subtitle",     webLog.subtitle
 | 
					                        "subtitle",     webLog.subtitle
 | 
				
			||||||
                        "defaultPage",  webLog.defaultPage
 | 
					                        "defaultPage",  webLog.defaultPage
 | 
				
			||||||
                        "postsPerPage", webLog.postsPerPage
 | 
					                        "postsPerPage", webLog.postsPerPage
 | 
				
			||||||
                        "timeZone",     webLog.timeZone
 | 
					                        "timeZone",     webLog.timeZone
 | 
				
			||||||
                        "themePath",    webLog.themePath
 | 
					                        "themePath",    webLog.themePath
 | 
				
			||||||
                        "autoHtmx",     webLog.autoHtmx
 | 
					                        "autoHtmx",     webLog.autoHtmx
 | 
				
			||||||
 | 
					                        "uploads",      webLog.uploads
 | 
				
			||||||
                    ]
 | 
					                    ]
 | 
				
			||||||
                    write; withRetryDefault; ignoreResult conn
 | 
					                    write; withRetryDefault; ignoreResult conn
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -856,6 +856,9 @@ type SettingsModel =
 | 
				
			|||||||
    {   /// The name of the web log
 | 
					    {   /// The name of the web log
 | 
				
			||||||
        name : string
 | 
					        name : string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// The slug of the web log
 | 
				
			||||||
 | 
					        slug : string
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// The subtitle of the web log
 | 
					        /// The subtitle of the web log
 | 
				
			||||||
        subtitle : string
 | 
					        subtitle : string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -873,29 +876,36 @@ type SettingsModel =
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        /// Whether to automatically load htmx
 | 
					        /// Whether to automatically load htmx
 | 
				
			||||||
        autoHtmx : bool
 | 
					        autoHtmx : bool
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// The default location for uploads
 | 
				
			||||||
 | 
					        uploads : string
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Create a settings model from a web log
 | 
					    /// Create a settings model from a web log
 | 
				
			||||||
    static member fromWebLog (webLog : WebLog) =
 | 
					    static member fromWebLog (webLog : WebLog) =
 | 
				
			||||||
        { name         = webLog.name
 | 
					        { name         = webLog.name
 | 
				
			||||||
 | 
					          slug         = webLog.slug
 | 
				
			||||||
          subtitle     = defaultArg webLog.subtitle ""
 | 
					          subtitle     = defaultArg webLog.subtitle ""
 | 
				
			||||||
          defaultPage  = webLog.defaultPage
 | 
					          defaultPage  = webLog.defaultPage
 | 
				
			||||||
          postsPerPage = webLog.postsPerPage
 | 
					          postsPerPage = webLog.postsPerPage
 | 
				
			||||||
          timeZone     = webLog.timeZone
 | 
					          timeZone     = webLog.timeZone
 | 
				
			||||||
          themePath    = webLog.themePath
 | 
					          themePath    = webLog.themePath
 | 
				
			||||||
          autoHtmx     = webLog.autoHtmx
 | 
					          autoHtmx     = webLog.autoHtmx
 | 
				
			||||||
 | 
					          uploads      = UploadDestination.toString webLog.uploads
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /// Update a web log with settings from the form
 | 
					    /// Update a web log with settings from the form
 | 
				
			||||||
    member this.update (webLog : WebLog) =
 | 
					    member this.update (webLog : WebLog) =
 | 
				
			||||||
        { webLog with
 | 
					        { webLog with
 | 
				
			||||||
            name         = this.name
 | 
					            name         = this.name
 | 
				
			||||||
 | 
					            slug         = this.slug
 | 
				
			||||||
            subtitle     = if this.subtitle = "" then None else Some this.subtitle
 | 
					            subtitle     = if this.subtitle = "" then None else Some this.subtitle
 | 
				
			||||||
            defaultPage  = this.defaultPage
 | 
					            defaultPage  = this.defaultPage
 | 
				
			||||||
            postsPerPage = this.postsPerPage
 | 
					            postsPerPage = this.postsPerPage
 | 
				
			||||||
            timeZone     = this.timeZone
 | 
					            timeZone     = this.timeZone
 | 
				
			||||||
            themePath    = this.themePath
 | 
					            themePath    = this.themePath
 | 
				
			||||||
            autoHtmx     = this.autoHtmx
 | 
					            autoHtmx     = this.autoHtmx
 | 
				
			||||||
 | 
					            uploads      = UploadDestination.parse this.uploads
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -475,11 +475,15 @@ let settings : HttpHandler = fun next ctx -> task {
 | 
				
			|||||||
                           |> List.map (fun p -> KeyValuePair.Create (PageId.toString p.id, p.title))
 | 
					                           |> List.map (fun p -> KeyValuePair.Create (PageId.toString p.id, p.title))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                |> Array.ofSeq
 | 
					                |> Array.ofSeq
 | 
				
			||||||
            themes     = themes
 | 
					            themes =
 | 
				
			||||||
                         |> Seq.ofList
 | 
					                themes
 | 
				
			||||||
                         |> Seq.map (fun it ->
 | 
					                 |> Seq.ofList
 | 
				
			||||||
                             KeyValuePair.Create (ThemeId.toString it.id, $"{it.name} (v{it.version})"))
 | 
					                 |> Seq.map (fun it -> KeyValuePair.Create (ThemeId.toString it.id, $"{it.name} (v{it.version})"))
 | 
				
			||||||
                         |> Array.ofSeq
 | 
					                 |> Array.ofSeq
 | 
				
			||||||
 | 
					            upload_values =
 | 
				
			||||||
 | 
					                [|  KeyValuePair.Create (UploadDestination.toString Database, "Database")
 | 
				
			||||||
 | 
					                    KeyValuePair.Create (UploadDestination.toString Disk,     "Disk")
 | 
				
			||||||
 | 
					                |]
 | 
				
			||||||
            web_log    = webLog
 | 
					            web_log    = webLog
 | 
				
			||||||
            page_title = "Web Log Settings"
 | 
					            page_title = "Web Log Settings"
 | 
				
			||||||
        |}
 | 
					        |}
 | 
				
			||||||
@ -493,12 +497,19 @@ let saveSettings : HttpHandler = fun next ctx -> task {
 | 
				
			|||||||
    let! model  = ctx.BindFormAsync<SettingsModel> ()
 | 
					    let! model  = ctx.BindFormAsync<SettingsModel> ()
 | 
				
			||||||
    match! data.WebLog.findById webLog.id with
 | 
					    match! data.WebLog.findById webLog.id with
 | 
				
			||||||
    | Some webLog ->
 | 
					    | Some webLog ->
 | 
				
			||||||
        let webLog = model.update webLog
 | 
					        let oldSlug = webLog.slug
 | 
				
			||||||
 | 
					        let webLog  = model.update webLog
 | 
				
			||||||
        do! data.WebLog.updateSettings webLog
 | 
					        do! data.WebLog.updateSettings webLog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Update cache
 | 
					        // Update cache
 | 
				
			||||||
        WebLogCache.set webLog
 | 
					        WebLogCache.set webLog
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        if oldSlug <> webLog.slug then
 | 
				
			||||||
 | 
					            // Rename disk directory if it exists
 | 
				
			||||||
 | 
					            let uploadRoot = Path.Combine ("wwwroot", "upload")
 | 
				
			||||||
 | 
					            let oldDir     = Path.Combine (uploadRoot, oldSlug)
 | 
				
			||||||
 | 
					            if Directory.Exists oldDir then Directory.Move (oldDir, Path.Combine (uploadRoot, webLog.slug))
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
        do! addMessage ctx { UserMessage.success with message = "Web log settings saved successfully" }
 | 
					        do! addMessage ctx { UserMessage.success with message = "Web log settings saved successfully" }
 | 
				
			||||||
        return! redirectToGet (WebLog.relativeUrl webLog (Permalink "admin/settings")) next ctx
 | 
					        return! redirectToGet (WebLog.relativeUrl webLog (Permalink "admin/settings")) next ctx
 | 
				
			||||||
    | None -> return! Error.notFound next ctx
 | 
					    | None -> return! Error.notFound next ctx
 | 
				
			||||||
 | 
				
			|||||||
@ -8,26 +8,33 @@
 | 
				
			|||||||
    <input type="hidden" name="{{ csrf.form_field_name }}" value="{{ csrf.request_token }}">
 | 
					    <input type="hidden" name="{{ csrf.form_field_name }}" value="{{ csrf.request_token }}">
 | 
				
			||||||
    <div class="container">
 | 
					    <div class="container">
 | 
				
			||||||
      <div class="row">
 | 
					      <div class="row">
 | 
				
			||||||
        <div class="col-12 col-md-6 col-xl-4 offset-xl-1 pb-3">
 | 
					        <div class="col-12 col-md-6 col-xl-4 pb-3">
 | 
				
			||||||
          <div class="form-floating">
 | 
					          <div class="form-floating">
 | 
				
			||||||
            <input type="text" name="name" id="name" class="form-control" value="{{ model.name }}" required autofocus>
 | 
					            <input type="text" name="name" id="name" class="form-control" placeholder="Name" required autofocus
 | 
				
			||||||
 | 
					                   value="{{ model.name }}">
 | 
				
			||||||
            <label for="name">Name</label>
 | 
					            <label for="name">Name</label>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="col-12 col-md-6 col-xl-4 pb-3">
 | 
					        <div class="col-12 col-md-6 col-xl-4 pb-3">
 | 
				
			||||||
          <div class="form-floating">
 | 
					          <div class="form-floating">
 | 
				
			||||||
            <input type="text" name="subtitle" id="subtitle" class="form-control" value="{{ model.subtitle }}">
 | 
					            <input type="text" name="slug" id="slug" class="form-control" placeholder="Slug" required
 | 
				
			||||||
 | 
					                   value="{{ model.slug }}">
 | 
				
			||||||
 | 
					            <label for="slug">Slug</label>
 | 
				
			||||||
 | 
					            <span class="form-text">
 | 
				
			||||||
 | 
					              <span class="badge rounded-pill bg-warning text-dark">WARNING</span> changing this value may break links
 | 
				
			||||||
 | 
					              (<a href="https://bitbadger.solutions/open-source/myweblog/configuring.html#blog-settings"
 | 
				
			||||||
 | 
					                  target="_blank">more</a>)
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="col-12 col-md-6 col-xl-4 pb-3">
 | 
				
			||||||
 | 
					          <div class="form-floating">
 | 
				
			||||||
 | 
					            <input type="text" name="subtitle" id="subtitle" class="form-control" placeholder="Subtitle"
 | 
				
			||||||
 | 
					                   value="{{ model.subtitle }}">
 | 
				
			||||||
            <label for="subtitle">Subtitle</label>
 | 
					            <label for="subtitle">Subtitle</label>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="col-12 col-md-4 col-xl-2 pb-3">
 | 
					        <div class="col-12 col-md-6 col-xl-4 offset-xl-1 pb-3">
 | 
				
			||||||
          <div class="form-floating">
 | 
					 | 
				
			||||||
            <input type="number" name="postsPerPage" id="postsPerPage" class="form-control" min="0" max="50" required
 | 
					 | 
				
			||||||
                   value="{{ model.posts_per_page }}">
 | 
					 | 
				
			||||||
            <label for="postsPerPage">Posts per Page</label>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="col-12 col-md-4 col-xl-3 pb-3">
 | 
					 | 
				
			||||||
          <div class="form-floating">
 | 
					          <div class="form-floating">
 | 
				
			||||||
            <select name="themePath" id="themePath" class="form-control" required>
 | 
					            <select name="themePath" id="themePath" class="form-control" required>
 | 
				
			||||||
              {% for theme in themes -%}
 | 
					              {% for theme in themes -%}
 | 
				
			||||||
@ -39,19 +46,12 @@
 | 
				
			|||||||
            <label for="themePath">Theme</label>
 | 
					            <label for="themePath">Theme</label>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="col-12 col-md-4 col-xl-3 pb-3">
 | 
					        <div class="col-12 col-md-6 offset-md-1 col-xl-4 offset-xl-0 pb-3">
 | 
				
			||||||
          <div class="form-floating">
 | 
					 | 
				
			||||||
            <input type="text" name="timeZone" id="timeZone" class="form-control" required
 | 
					 | 
				
			||||||
                   value="{{ model.time_zone }}">
 | 
					 | 
				
			||||||
            <label for="timeZone">Time Zone</label>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="col-12 col-md-4 pb-3">
 | 
					 | 
				
			||||||
          <div class="form-floating">
 | 
					          <div class="form-floating">
 | 
				
			||||||
            <select name="defaultPage" id="defaultPage" class="form-control" required>
 | 
					            <select name="defaultPage" id="defaultPage" class="form-control" required>
 | 
				
			||||||
              {% for pg in pages -%}
 | 
					              {% for pg in pages -%}
 | 
				
			||||||
                <option value="{{ pg[0] }}"
 | 
					                <option value="{{ pg[0] }}"
 | 
				
			||||||
                        {%- if pg[0] == model.default_page  %} selected="selected"{% endif %}>
 | 
					                {%- if pg[0] == model.default_page  %} selected="selected"{% endif %}>
 | 
				
			||||||
                  {{ pg[1] }}
 | 
					                  {{ pg[1] }}
 | 
				
			||||||
                </option>
 | 
					                </option>
 | 
				
			||||||
              {%- endfor %}
 | 
					              {%- endfor %}
 | 
				
			||||||
@ -59,6 +59,22 @@
 | 
				
			|||||||
            <label for="defaultPage">Default Page</label>
 | 
					            <label for="defaultPage">Default Page</label>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="col-12 col-md-4 col-xl-2 pb-3">
 | 
				
			||||||
 | 
					          <div class="form-floating">
 | 
				
			||||||
 | 
					            <input type="number" name="postsPerPage" id="postsPerPage" class="form-control" min="0" max="50" required
 | 
				
			||||||
 | 
					                   value="{{ model.posts_per_page }}">
 | 
				
			||||||
 | 
					            <label for="postsPerPage">Posts per Page</label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="row">
 | 
				
			||||||
 | 
					        <div class="col-12 col-md-4 col-xl-3 offset-xl-2 pb-3">
 | 
				
			||||||
 | 
					          <div class="form-floating">
 | 
				
			||||||
 | 
					            <input type="text" name="timeZone" id="timeZone" class="form-control" placeholder="Time Zone" required
 | 
				
			||||||
 | 
					                   value="{{ model.time_zone }}">
 | 
				
			||||||
 | 
					            <label for="timeZone">Time Zone</label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        <div class="col-12 col-md-4 col-xl-2">
 | 
					        <div class="col-12 col-md-4 col-xl-2">
 | 
				
			||||||
          <div class="form-check form-switch">
 | 
					          <div class="form-check form-switch">
 | 
				
			||||||
            <input type="checkbox" name="autoHtmx" id="autoHtmx" class="form-check-input" value="true"
 | 
					            <input type="checkbox" name="autoHtmx" id="autoHtmx" class="form-check-input" value="true"
 | 
				
			||||||
@ -69,6 +85,16 @@
 | 
				
			|||||||
            <a href="https://htmx.org" target="_blank" rel="noopener">What is this?</a>
 | 
					            <a href="https://htmx.org" target="_blank" rel="noopener">What is this?</a>
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="col-12 col-md-4 col-xl-3 pb-3">
 | 
				
			||||||
 | 
					          <div class="form-floating">
 | 
				
			||||||
 | 
					            <select name="uploads" id="uploads" class="form-control">
 | 
				
			||||||
 | 
					              {%- for it in upload_values %}
 | 
				
			||||||
 | 
					                <option value="{{ it[0] }}"{% if model.uploads == it[0] %} selected{% endif %}>{{ it[1] }}</option>
 | 
				
			||||||
 | 
					              {%- endfor %}
 | 
				
			||||||
 | 
					            </select>
 | 
				
			||||||
 | 
					            <label for="uploads">Default Upload Destination</label>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="row pb-3">
 | 
					      <div class="row pb-3">
 | 
				
			||||||
        <div class="col text-center">
 | 
					        <div class="col text-center">
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user