╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ NewUser.zig ──────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯
116 117 fn formField(form: *wgt.Box(ui.Widget), name: []const u8) !*wgt.TextInput { 118 for (form.children.values()) |*child| switch (child.widget) { 119 .text_input => |*text_input| if (std.mem.eql(u8, text_input.options.name, name)) return text_input, 120 else => {}, 121 }; 122 return error.MissingFormField; 123 } 124 125 // create the user, log in, and navigate to their page. this is the 126 // terminal path; the web posts the form to the new-user route. 127 fn submitForm(self: *View, allocator: std.mem.Allocator) !void { 128 if (comptime wasm) return; 129 const io = self.session.io orelse return; 130 const users_dir = self.session.users_dir orelse return; 131 const admin_repo = self.session.admin_repo orelse return; 132 133 const name_input = try formField(self.formBox(), "name"); 134 const email_input = try formField(self.formBox(), "email"); 135 const password_input = try formField(self.formBox(), "password"); 136 const password_again_input = try formField(self.formBox(), "password_again"); 137 const name = try name_input.text(allocator); 138 defer allocator.free(name); 139 const email = try email_input.text(allocator); 140 defer allocator.free(email); 141 const password = try password_input.text(allocator); 142 defer allocator.free(password); 143 const password_again = try password_again_input.text(allocator); 144 defer allocator.free(password_again); 145 146 const id = evt.createUser(io, allocator, users_dir, admin_repo, name, email, password, password_again) catch |err| { 147 const aa = self.session.arena.allocator(); 148 self.session.data.form_feedback = .{ .user = .{ 149 .failure = ui.Session.FormFeedback.UserFailure.fromError(err) orelse return err, 150 .fields = .{ .name = try aa.dupe(u8, name), .email = try aa.dupe(u8, email) }, 151 } }; 152 return; 153 }; 154 155 // log in as the new user, reading them from a moment that has them 156 self.session.data.user_id = try self.session.arena.allocator().dupe(u8, &id); 157 try self.session.rememberSshKey(); 158 self.session.haxy_moment = try evt.currentMoment(evt.admin_repo_opts, admin_repo); 159 try self.session.loadUser(); 160 161 // wipe the form so a return visit starts fresh 162 name_input.clear(allocator); 163 email_input.clear(allocator); 164 password_input.clear(allocator); 165 password_again_input.clear(allocator); 166 167 try self.session.navigate(.{ .user_repos = .{ .name = ui.RoutablePage.Array(evt.User.name_max_len).from(name) orelse return error.RouteTooLong } }); 168 } 169 170 fn formBox(self: *View) *wgt.Box(ui.Widget) { 171 return &self.center.child.box; 172 } 173 174 pub fn clearGrid(self: *View) void { 175 self.center.clearGrid(); 176 } 177 178 pub fn getGrid(self: View) ?Grid { 179 return self.center.getGrid(); 180 } 181 182 pub fn getFocus(self: *View) *Focus { 183 return self.center.getFocus(); 184 } 185 186 // up leaves the form from its first control 187 pub fn atTop(self: View) bool { 188 const box = &self.center.child.box; 189 return box.focus.child_id == box.children.keys()[0]; 190 } 191 }; 192