Updated smart form
This commit is contained in:
parent
92607260d1
commit
78eb4050ae
4 changed files with 109 additions and 62 deletions
43
notarize.js
43
notarize.js
|
|
@ -2,8 +2,9 @@ const exec = require('child_process').exec;
|
|||
const sign = require("electron-osx-sign").signAsync;
|
||||
const notarize = require("electron-notarize").notarize;
|
||||
|
||||
const app = "Crimata.app";
|
||||
const dir = `${app}/Contents/Resources/app`;
|
||||
const name = "Crimata";
|
||||
const dir = `${name}.app/Contents/Resources/app`;
|
||||
const registry = "https://gitlab.com/api/v4/projects/25637892/packages/generic/crimata/0.0.1/Crimata.zip";
|
||||
|
||||
const runShellCommand = (cmd) => (new Promise((resolve, reject) => {
|
||||
exec(cmd, (error, stdout, stderr) => {
|
||||
|
|
@ -11,8 +12,11 @@ const runShellCommand = (cmd) => (new Promise((resolve, reject) => {
|
|||
});
|
||||
}));
|
||||
|
||||
// /projects/:id/packages/generic/:package_name/:package_version/:file_name?status=:status
|
||||
|
||||
|
||||
const signConfig = {
|
||||
"app": app,
|
||||
"app": name + ".app",
|
||||
"hardened-runtime": true,
|
||||
"gatekeeper-assess": false,
|
||||
"signature-flags": "library",
|
||||
|
|
@ -21,7 +25,7 @@ const signConfig = {
|
|||
};
|
||||
|
||||
const notarizeConfig = {
|
||||
appPath: app,
|
||||
appPath: name + ".app",
|
||||
appleId: "gundersena@crimata.com",
|
||||
appBundleId: "com.crimata.CrimataMessenger",
|
||||
appleIdPassword: process.env["AC_PASSWORD"]
|
||||
|
|
@ -31,18 +35,24 @@ const notarizeConfig = {
|
|||
|
||||
try
|
||||
{
|
||||
console.log("Building...");
|
||||
await runShellCommand(`rm -rf ${dir} && mkdir ${dir} && cp -r {package.json,src,node_modules} ${dir}
|
||||
`);
|
||||
// console.log("Building...");
|
||||
// await runShellCommand(`rm -rf ${dir} && mkdir ${dir} && cp -r {package.json,src,node_modules} ${dir}
|
||||
// `);
|
||||
|
||||
console.log("Cleaning...");
|
||||
await runShellCommand(`xattr -cr ${app}`);
|
||||
// console.log("Cleaning...");
|
||||
// await runShellCommand(`xattr -cr ${name}.app`);
|
||||
|
||||
console.log("Signing...");
|
||||
await sign(signConfig);
|
||||
// console.log("Signing...");
|
||||
// await sign(signConfig);
|
||||
|
||||
console.log("Notarizing...");
|
||||
await notarize(notarizeConfig);
|
||||
// console.log("Notarizing...");
|
||||
// await notarize(notarizeConfig);
|
||||
|
||||
// console.log("Compressing...");
|
||||
// await runShellCommand(`zip -vr ${name}.zip ${name}.app`);
|
||||
|
||||
console.log("Uploading to Gitlab...");
|
||||
await runShellCommand(`curl --header "PRIVATE-TOKEN: ${process.env["API_TOKEN"]}" --upload-file ${name}.zip "${registry}"`);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
|
|
@ -50,3 +60,10 @@ const notarizeConfig = {
|
|||
}
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* Copy file from local to remote:
|
||||
*
|
||||
* scp -r Electron.app gundersena@crimata-server:~/Desktop/crimata/website/assets
|
||||
*/
|
||||
23
src/render/components/control/valid.js
Normal file
23
src/render/components/control/valid.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
export const isEmail = (value) => {
|
||||
console.log(value);
|
||||
if (!/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(value)) {
|
||||
return "Not a valid email."
|
||||
}
|
||||
}
|
||||
|
||||
export const isPassword = (value) => {
|
||||
if (!/^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$/.test(value)) {
|
||||
return "Password must have symbol, number, uppercase and be 6-16 length.";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Name is optional and therefore doesn't return error if no value.
|
||||
*/
|
||||
export const isName = (value) => {
|
||||
if (value) {
|
||||
if (!/^([a-zA-Z ]){5,30}$/.test(value)) {
|
||||
return "Name must be at least 5 long.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +1,86 @@
|
|||
|
||||
// Basic debounce implentation
|
||||
const debounce = (fn, delay) => {
|
||||
|
||||
let timeoutId;
|
||||
|
||||
const wrapper = (...args) => {
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
return (...args) => {
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
fn(...args);
|
||||
}, delay);
|
||||
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const SmartForm =
|
||||
/**
|
||||
* Dynamic form component with auto submission and validation.
|
||||
*
|
||||
* props
|
||||
* .fields => List of field objects
|
||||
* .channel => e.g. "/login"
|
||||
* .modifier => Form description
|
||||
*/
|
||||
const SmartForm =
|
||||
{
|
||||
props: ["fields", "channel", "modifier"],
|
||||
|
||||
setup(props)
|
||||
{
|
||||
let logsEl;
|
||||
// Error log below form
|
||||
const log = Vue.ref(props.modifier);
|
||||
|
||||
const submit = debounce(async (data) => {
|
||||
/**
|
||||
* Valid and submit form data to channel.
|
||||
*/
|
||||
const submit = async () => {
|
||||
|
||||
let object = {};
|
||||
data.forEach(function(value, key){
|
||||
object[key] = value;
|
||||
});
|
||||
|
||||
const err = await window.mainApi.invoke(props.channel, object)
|
||||
|
||||
if (err) {
|
||||
logsEl.innerText = err;
|
||||
logsEl.style.color = "red";
|
||||
return;
|
||||
// Validate each field
|
||||
for (let field of props.fields) {
|
||||
const error = field.valid(field.value);
|
||||
if (error) return error;
|
||||
}
|
||||
|
||||
logsEl.style.color = "green";
|
||||
logsEl.innerText = props.modifier;
|
||||
// Reduce fields into the form
|
||||
const form = props.fields.reduce((v, n) => {
|
||||
v[n.name] = n.value;
|
||||
return v;
|
||||
}, {});
|
||||
|
||||
console.log("Submitting =>", form);
|
||||
return await window.mainApi.invoke(props.channel, form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for submit that is debounced and updates UI elements
|
||||
*/
|
||||
const preSub = debounce(async () => {
|
||||
|
||||
const error = await submit();
|
||||
|
||||
log.value = error ? error : props.modifier
|
||||
|
||||
}, 2000);
|
||||
|
||||
Vue.onMounted(() => {
|
||||
|
||||
const el = document.getElementById("smart-form");
|
||||
|
||||
logsEl = el.querySelector(".smart-form-logs");
|
||||
|
||||
logsEl.innerText = props.modifier;
|
||||
|
||||
el.addEventListener("input", () => {
|
||||
submit(new FormData(el))
|
||||
});
|
||||
|
||||
});
|
||||
return { preSub, log };
|
||||
},
|
||||
|
||||
template: `
|
||||
<form id="smart-form" class="smart-form">
|
||||
<form id="smart-form" class="smart-form" v-on:input="preSub">
|
||||
|
||||
<div v-for="field in fields" style="display:flex">
|
||||
|
||||
<input type="text" class="text-field"
|
||||
<input type="text" class="text-field"
|
||||
v-model="field.value"
|
||||
:name="field.name"
|
||||
:value="field.value"
|
||||
:placeholder="field.placeholder"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="smart-form-logs"></div>
|
||||
<div class="smart-form-logs">{{ log }}</div>
|
||||
|
||||
</form>`
|
||||
}
|
||||
|
||||
export default SmartForm;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import SmartForm from "./form.js";
|
||||
import { isEmail, isPassword, isName } from "./control/valid.js";
|
||||
|
||||
const Login =
|
||||
{
|
||||
|
|
@ -8,7 +9,7 @@ const Login =
|
|||
|
||||
setup()
|
||||
{
|
||||
return;
|
||||
return { isEmail, isPassword, isName };
|
||||
},
|
||||
|
||||
template: `
|
||||
|
|
@ -19,16 +20,19 @@ const Login =
|
|||
name: 'email',
|
||||
value: null,
|
||||
placeholder: 'Email',
|
||||
valid: isEmail
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
value: null,
|
||||
placeholder: 'Password'
|
||||
placeholder: 'Password',
|
||||
valid: isPassword
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
value: null,
|
||||
placeholder: 'Name'
|
||||
placeholder: 'Name',
|
||||
valid: isName
|
||||
}]"
|
||||
:channel="'auth'"
|
||||
:modifier="'Login or enter name to register.'"
|
||||
|
|
@ -37,4 +41,4 @@ const Login =
|
|||
</div>`
|
||||
}
|
||||
|
||||
export default Login;
|
||||
export default Login;
|
||||
|
|
|
|||
Loading…
Reference in a new issue