Add global music player, invoicing/payment system, account subpages, mail account admin, and the qualityiron.vegas Jet 2.0 port

Jet interpreter (Tag.cpp, __call.cpp, __imap*.cpp/h, __smtpsend.cpp/h,
__imapemptyfolder.cpp/h - new): assorted parser/tag fixes found across
this work - a stray literal-tag-in-comment and backslash-quote parser
corruption class, a dangling-pointer fix, a __call.cpp fd leak, IMAP
folder-management tags, multi-account/per-host IMAP support, and a
smtpsend Message-ID fix.

barant.com site (jetc/barant-site/):
- A site-wide persistent music player (header band, playlist/queue,
  stereo FFT EQ, session-persisted state) fed by new library/
  ianslibrary/music song-list subpages.
- /account split into info/phones/invoices subpages; a full invoicing
  and Square payment system (create/edit/copy/pay/email invoice);
  admin invoice management and mail-account management subpages.
- /services split into overview/hosting/siptrunking/documents
  subpages, retiring the old standalone pages.
- SIPPHONE.tag: a Jet 2.0 WebRTC softphone tag.
- main.css/spa.js/email.js: the SPA loading indicator, the music
  player band styling, and assorted fixes accumulated alongside this
  work.

qualityiron-site/: the qualityiron.vegas job/contractor/customer/
document management app, ported from its original Jet 1.4 codebase to
Jet 2.0 as barant.coms APIServers second multi-tenant site.

wcwc/wcwc.jet: the WCWC site Jet source (wcwc.jtc build output not
included).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Brad ArantandClaude Sonnet 5 committed 2026-10-06 17:42:01 +00:00
1 parent 905fbafa5a
commit b8f7793773
406 files changed
+15803 -587

No files matched your search

+255
View File
@@ -0,0 +1,255 @@
<tag name="ifadmin">
<if value1="$[__admin__]" value2="1" type="eq">
<container>
</if>
</tag>
<tag name="ifnotadmin">
<if value1="$[__admin__]" value2="0" type="eq">
<container>
</if>
</tag>
<tag name="retain" keywords="name value empty">
<if value1="#[empty]" value2="" type=eq>
<if value1="#[value]" value2="" type=eq>
<set name='tmp_#[name]' value="$[#[name]]" format=tobrowser>
<input type="hidden" name="#[name]" value="$[tmp_#[name]]">
<else>
<set name='tmp_#[name]' value="#[value]" format=tobrowser>
<input type="hidden" name="#[name]" value="$[tmp_#[name]]">
</if>
<else>
<input type="hidden" name="#[name]" value="">
</if>
</tag>
<tag name="linkbutton" keywords="pagedir page subpage process name name2 value value2 target class multipart">
<A HREF="javascript:
<IF VALUE1="#[PAGEDIR]" VALUE2="" TYPE=NE>
<SET NAME=X_LEVEL EXPR="$[N_LEVEL] + 1">
</IF>
<IF VALUE1="#[PROCESS]" VALUE2="" TYPE="EQ">
document.forms[0].PROCESS.value='';
<ELSE>
document.forms[0].PROCESS.value='#[PROCESS]';
</IF>
<IF VALUE1="#[PAGE]" VALUE2="" TYPE="EQ">
document.forms[0].PAGE.value='$[PAGE]';
<ELSE>
document.forms[0].PAGE.value='#[PAGE]';
</IF>
<IF VALUE1="#[SUBPAGE]" VALUE2="" TYPE="EQ">
document.forms[0].SUBPAGE.value='';
<ELSE>
document.forms[0].SUBPAGE.value='#[SUBPAGE]';
</IF>
<IF VALUE1="#[NAME]" VALUE2="" TYPE="NE">
document.forms[0].#[NAME].value='#[VALUE]';
</IF>
<IF VALUE1="#[NAME2]" VALUE2="" TYPE="NE">
document.forms[0].#[NAME2].value='#[VALUE2]';
</IF>
<IF VALUE1="#[MULTIPART]" VALUE2="YES" TYPE="EQ">
document.forms[0].encoding='multipart/form-data';
</IF>
<IF VALUE1="#[TARGET]" VALUE2="" TYPE="NE">
document.forms[0].target='#[TARGET]';
</IF>
<IF VALUE1="#[PAGEDIR]" VALUE2="" TYPE="NE">
document.forms[0].P_$[L_LEVEL].value='$[PAGE]';
document.forms[0].L_$[L_LEVEL].value='$[X_TITLE]';
document.forms[0].D_$[N_LEVEL].value='#[PAGEDIR]';
document.forms[0].P_$[N_LEVEL].value='#[PAGE]';
document.forms[0].P_LEVEL.value=$[L_LEVEL];
document.forms[0].L_LEVEL.value=$[N_LEVEL];
document.forms[0].N_LEVEL.value='$[X_LEVEL]';
</IF>
document.forms[0].target='';
document.forms[0].requestSubmit();"
<if value1="#[CLASS]" value2="" type="ne">
CLASS="#[CLASS]"
</if>
><EVAL><CONTAINER></EVAL></A>
</TAG>
<TAG NAME="ABUTTON" KEYWORDS="PAGE PROCESS NAME VALUE MULTIPART">
<BUTTON ONCLICK="javascript:
<IF VALUE1="#[PAGE]" VALUE2="" TYPE="NE">
document.forms[0].PAGE.value='#[PAGE]';
<else>
document.forms[0].PAGE.value='$[PAGE]';
</IF>
<IF VALUE1="#[PROCESS]" VALUE2="" TYPE="NE">
document.forms[0].PROCESS.value='#[PROCESS]';
</IF>
<IF VALUE1="#[NAME]" VALUE2="" TYPE="NE">
document.forms[0].#[NAME].value='#[VALUE]';
</IF>
<IF VALUE1="#[MULTIPART]" VALUE2="YES" TYPE="EQ">
document.forms[0].encoding='multipart/form-data';
</IF>
document.forms[0].requestSubmit();">&nbsp;<CONTAINER>&nbsp;</BUTTON>
</TAG>
<tag name="setenv" keywords="name">
<eval name="_envvalue" scope="local"><container></eval>
<set name="#[name]" value="#[_envvalue]">
<set name="@#[name]" value="#[_envvalue]">
</tag>
<tag name="clearenv" keywords="name">
<set name="#[name]" value="">
<set name="@#[name]" value="">
</tag>
<tag name="setpage" keywords="NAME DIR">
<SET NAME=PAGE VALUE='#[NAME]'>
<IF VALUE1="#[DIR]" VALUE2="" TYPE="NE">
<SET NAME="DIR" VALUE="$[DIR]/#[DIR]">
<set name="_CTLDIR" value="$[DIR]">
</IF>
</TAG>
<TAG NAME='SETPROCESS' KEYWORDS='VALUE'>
<SET NAME=PROCESS VALUE='#[VALUE]'>
</TAG>
<tag name="checksession">
<set name="_login_id" value="$[@_login_id]">
<set name="_login_name" value="$[@_login_name]">
<set name="_login_email" value="$[@_login_email]">
<set name="_login_type" value="$[@_login_type]">
<set name="_login_uuid" value="$[@_login_uuid]">
</tag>
<tag name='sessionctl' keywords="page stylesheet">
<tag name="defaultnav"><if expr="('$[PAGE]' = '') and ('$[PROCESS]' = '')"><eval><container></eval></if></tag>
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="_SESSIONCTL">
<tag name='fetchpage'>
<tag name="directory" keywords="NAME PAGE">
<set name="DIR" value="$[DIR]/#[NAME]">
<set name="PAGE" value="#[PAGE]">
<fetchpage>
</tag>
<tag name="page" keywords="template class onload secure loggedin admin" scope="local">
<tag name="author" scope="local"><eval name="AUTHOR" scope="parent"><container></eval></tag>
<tag name="description" scope="local"><container name="description" eval="no" scope="parent"></tag>
<tag name="keywords" scope="local"><container name="keywords" eval="no" scope="parent"></tag>
<tag name="contents" scope="local"><eval name="_BODY"><container></eval></tag>
<TAG NAME='TEMPLATE' SCOPE=LOCAL>
<tag name="contents" scope="local">
$[_BODY]
</TAG>
<EVAL NAME=TEMPLATEDATA SCOPE=PARENT><CONTAINER EVAL="NO"></EVAL>
</TAG>
<if expr="('$[HTTPS]'!='on') and ('#[secure]'='yes')">
<html><head><meta http-equiv="refresh" content="0; url=https://$[HTTP_HOST]$[REQUEST_URI]"></head></html>
<else>
<if expr="('$[_login_type]'='user') and ('#[admin]'='true')">
<include file="notfound.page">
<else>
<if expr="('$[_login_id]'='') and ('#[loggedin]'='yes')">
<html><head><meta http-equiv="refresh" content="0; url=https://$[HTTP_HOST]/login?start=$[PAGE]"></head></html>
<else>
<if expr="('$[_login_type]'='user') and ('#[admin]'='yes')">
<include file="notfound.page">
<else>
<!DOCTYPE html>
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
<head>
<eval><container eval="no"></eval>
<META NAME=AUTHOR CONTENT="#[AUTHOR]">
<META NAME=DESCRIPTION CONTENT="#[DESCRIPTION]">
<META NAME=KEYWORDS CONTENT="#[KEYWORDS]">
<if value1="$[_STYLESHEET]" value2="" type="NE">
<link rel="stylesheet" type="text/css" href="$[_STYLESHEET]">
</if>
$[head]
</head>
<body <if value1="#[CLASS]" value2="" type="ne">class="#[CLASS]"</if>
<if value1="#[onload]" value2="" type="ne">onload="#[onload]"</if>>
<form method="post" enctype="multipart/form-data" action="$[REQUEST_URI]">
<INPUT TYPE=HIDDEN NAME="_LASTPAGE" VALUE="$[PAGE]" >
<INPUT TYPE=HIDDEN NAME="PROCESS" VALUE="" >
<INPUT TYPE=HIDDEN NAME="EXITPROCESS" VALUE="$[EXITPROCESS]" >
<input type="hidden" name="DIR" value="$[DIR]">
<input type="hidden" name="_CTLDIR" value="$[_CTLDIR]">
<INPUT TYPE=HIDDEN NAME="PAGE" VALUE="$[PAGE]" >
<INPUT TYPE=HIDDEN NAME="_TIMESTAMP" VALUE="$[_timestamp]" >
<IF VALUE1="#[TEMPLATE]" VALUE2="" TYPE="EQ">
$[_BODY]
<ELSE>
<EVAL><INCLUDE FILE="./$[DIR]/#[TEMPLATE].temp"></EVAL>
#[TEMPLATEDATA]
</IF>
</form>
</body>
</html>
</if>
</if>
</if>
</if>
</TAG>
<eval><INCLUDE FILE="./$[DIR]/$[PAGE].page">
<if value1="$[ERROR]" value2="TRUE" type="eq">
<include file="notfound.page">
</if>
</eval>
</TAG>
<tag name="fetchproc">
<tag name="process">
<eval><container></eval>
</tag>
<EVAL><INCLUDE FILE="./$[DIR]/$[PROCESS].proc"></EVAL>
</TAG>
<tag name="virtual" keywords="SERVER DIR">
<if value1="$[PAGE]" value2="" type="eq">
<if value1="#[SERVER]" value2="$[$SERVER_NAME]" type="eq">
<set name="DIR" value="#[DIR]">
<set name="_CTLDIR" value="#[DIR]">
</if>
</if>
</tag>
<if value1="$[_session_id]" value2="" type="ne">
<checksession>
</if>
<eval name="head"><container></eval>
<if value1="$[PROCESS]" value2="" type="ne">
<fetchproc>
</if>
<if value1="$[PAGE]" value2="" type="eq">
<setpage name="#[PAGE]">
<else>
<script>window.history.replaceState('','','/$[PAGE]$[ARGS]');</script>
</if>
<fetchpage>
</database>
</tag>
@@ -0,0 +1,16 @@
<process>
<set name="x_address1" value="$[address1]">
<set name="x_address2" value="$[address2]">
<set name="x_city" value="$[city]">
<sql>insert into addresses set address1='$[x_address1]',
address2='$[x_address2]',
city='$[x_city]',
state='$[state]',
zip_code='$[zip_code]',
created=now(),
owner=$[@_login_id]
</sql>$[sqlerror]
<sql>select last_insert_id() as address_id</sql>$[sqlerror]
<set name="address_id" value="$[.address_id]">
<sql>insert into job_addresses set job_id=$[@_selected_job_id],address_id=$[address_id],address_type=$[address_type],created=now(),owner=$[@_login_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,12 @@
<process>
<set name="x_contact_name" value="$[contact_name]">
<sql>select * from contacts where name='$[x_contact_name]' and phone='$[phonex]' and email='$[emailx]'</sql>
<ifrow>
<set name="contact_id" value="$[.id]">
<else>
<sql>insert into contacts set name='$[x_contact_name]',phone='$[phonex]',email='$[emailx]',owner=$[@_login_id]</sql>$[sqlerror]
<sql>select last_insert_id() as contact_id</sql>$[sqlerror]
<set name="contact_id" value="$[.contact_id]">
</ifrow>
<sql>insert into job_contacts set job_id=$[@_selected_job_id],contact_id=$[contact_id],contact_type=$[contact_type],owner=$[@_login_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,10 @@
<process>
<set name="x_notation" value="$[job_notation]">
<sql>
insert into job_notation
set job_id=$[@_selected_job_id],
created=now(),
owner=$[@_login_id],
notation='$[x_notation]'
</sql>$[sqlerror]
</process>
+12
View File
@@ -0,0 +1,12 @@
<page>
<title>Quality Iron - Admin</title>
<contents>
<div>
<h1>ADMINISTRATION</h1>
<linkbutton page="users"><div style="text-align: center; padding: 5px 5px 0px 0px; background-color: #456; color: #fff; height: 35px; width: 200px;">Maintain Users</div></linkbutton><br>
<linkbutton page="roles"><div style="text-align: center; padding: 5px 5px 0px 0px; background-color: #456; color: #fff; height: 35px; width: 200px;">Maintain Roles</div></linkbutton><br>
<linkbutton page="editdoctypes"><div style="text-align: center; padding: 5px 5px 0px 0px; background-color: #567; color: #fff; height: 35px; width: 200px;">Edit Document Types</div></linkbutton><br>
<linkbutton page="editstatus"><div style="text-align: center; padding: 5px 5px 0px 0px; background-color: #678; color: #fff; height: 35px; width: 200px;">Edit Status Values</div></linkbutton><br>
</div>
</contents>
</page>
+15
View File
@@ -0,0 +1,15 @@
<div class="card">
<table>
<tr><th>Name:</th><td>$[name]</td></tr>
<tr><th>Address1:</th><td>$[address1]</td></tr>
<tr><th>Address2:</th><td>$[address2]</td></tr>
<tr><th>City:</th><td>$[city]</td></tr>
<tr><th>State:</th><td>$[state]</td></tr>
<tr><th>Zip Code:</th><td>$[zip_code]</td></tr>
<tr><th>Contact Name:</th><td>$[contact]</td></tr>
<tr><th>Contact Phone:</th><td>$[contact_phone]</td></tr>
<tr><th>Contact EMail:</th><td>$[contact_email]</td></tr>
<tr><th>Created:</th><td>$[created_date]</td></tr>
<tr><th>Owner:</th><td>$[owner_name]</td></tr>
</table>
</div>
+17
View File
@@ -0,0 +1,17 @@
<tr><td>Contractor Name:</td><td><input type="text" name="name" size="100" value="$[name]"></td></tr>
<tr><td>Address 1:</td><td><input type="text" name="address1" size="100" value="$[address1]"></td></tr>
<tr><td>Address 2:</td><td><input type="text" name="address2" size="100" value="$[address2]"></td></tr>
<tr><td>City:</td><td><input type="text" name="city" size="30" value="$[city]"></td></tr>
<tr><td>State:</td><td><select name="state">
<sql>select * from states</sql>
<whilerow>
<option value="$[.code]"
<if value1="NV" value2="$[.code]" type="eq">selected</if>
>$[.name]</option>
</whilerow>
</select>
</td></tr>
<tr><td>Zip Code:</td><td><input type="text" name="zip_code" size="10" value="$[zip_code]"></td></tr>
<tr><td>Contact Name:</td><td><input type="text" name="contact" size="50" value="$[contact]"></td></tr>
<tr><td>Contact Phone:</td><td><input type="text" name="contact_phone" size="20" value="$[contact_phone]"></td></tr>
<tr><td>Contact EMail:</td><td><input type="text" name="contact_email" size="50" value="$[contact_email]"></td></tr>
+70
View File
@@ -0,0 +1,70 @@
<page>
<title>Quality Iron - Contractor</title>
<contents>
<sql>
select contractors.*,
date_format(created, "%W, %M %D, %Y %l:%i%p") as created_date,
users.name as owner_name
from contractors
join users on contractors.owner=users.id
where contractors.id=$[@_selected_contractor_id]
</sql>$[sqlerror]
<h1>CONTRACTOR ($[.name])</h1>
<linkbutton page="editcontractor">Edit</linkbutton>
<set name="name" value="$[.name]">
<set name="address1" value="$[.address1]">
<set name="address2" value="$[.address2]">
<set name="city" value="$[.city]">
<set name="state" value="$[.state]">
<set name="zip_code" value="$[.zip_code]">
<set name="contact" value="$[.contact]">
<set name="contact_phone" value="$[.contact_phone]">
<set name="contact_email" value="$[.contact_email]">
<set name="created_date" value="$[.created_date]">
<set name="owner_name" value="$[.owner_name]">
<include file="qualityiron-site/contractor.card">
<retain name="selected_job_id">
<retain name="selected_customer_id">
<div>
<h1>JOBS</h1>
<div style="padding: 5px;">
<sql>
select *,
jobs.id as job_id,
customers.name as customer,
contractors.name as contractor
from jobs
left outer join customers on jobs.customer_id=customers.id
join contractors on jobs.contractor_id=contractors.id
join status on jobs.status_id=status.id
where contractor_id=$[@_selected_contractor_id]
order by job_name</sql>$[sqlerror]
<ifrow>
<div style="display: inline-block;">Jobs</div>
<div>
<table id="list">
<tr>
<th></th>
<th>Job Number</th>
<th>Customer</th>
<th>Insurance</th>
<th>Status</th>
</tr>
<whilerow>
<tr style="visibility: table-row">
<td><linkbutton page="job" process="selectjob" name="selected_job_id" value="$[.job_id]">Open</linkbutton></td>
<td>$[.job_number]</td>
<td>$[.customer] <linkbutton page="customer" process="selectcustomer" name="selected_customer_id" value="$[.customer_id]"><img src="/assets/open.png" align="right"></linkbutton></td>
<td>$[.insurance]</td>
<td>$[.description]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</div>
</contents>
</page>
@@ -0,0 +1,65 @@
<page>
<title>Quality Iron</title>
<contents>
<script>
function setrows(include) {
var table = document.getElementById("list");
for (var i = 1; row = table.rows[i]; i++) {
if(include == "") {
row.style.visibility = "visible";
} else {
row.style.visibility = "collapse";
}
for (var j = 0; col = row.cells[j]; j++) {
if(col.innerHTML.toUpperCase().includes(include.toUpperCase())) {
row.style.visibility = "visible";
}
}
}
}
</script>
<retain name="selected_contractor_id">
<div>
<h1>CONTRACTORS</h1>
<div style="padding: 5px;">
<div style="display: inline-block;"><linkbutton page="createcontractor">Create Contractor</linkbutton></div>
<sql>
select *
from contractors
order by name</sql>$[sqlerror]
<ifrow>
<div style="display: inline-block;">Contractors</div>
<div style="border-radius: 5px; display: inline-block; background: #345; color: #def; margin-left: 20px; padding: 5px;">
<img style="margin-top: 3px;" src="/assets/magglass.png" width="20px;" align="top">
<input style="font-size: 20px; color: #def;" type="text" size="10" name="search" value="" onkeyup="setrows(this.value); return true;">
</div>
</div>
<div>
<table id="list">
<tr>
<th></th>
<th>Name</th>
<th>Address</th>
<th>Contact Name</th>
<th>Contact Phone</th>
<th>Contact EMail</th>
<th>Created</th>
</tr>
<whilerow>
<tr style="visibility: table-row">
<td><linkbutton page="contractor" process="selectcontractor" name="selected_contractor_id" value="$[.id]">Open</linkbutton></td>
<td>$[.name]</td>
<td>$[.address1] $[.address2], $[.city] $[.state], $[.zip_code]</td>
<td>$[.contact]</td>
<td>$[.contact_phone]</td>
<td>$[.contact_email]</td>
<td>$[.created]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</contents>
</page>
@@ -0,0 +1,14 @@
<page>
<title>Quality Iron - Create Contractor</title>
<contents>
<div>
<h1>CREATE CONTRACTOR</h1>
<div>
<table>
<include file="qualityiron-site/contractor.form">
</table>
</div>
<abutton process="createcontractor" page="contractors">Create Contractor</abutton>
</div>
</contents>
</page>
@@ -0,0 +1,20 @@
<process>
<set name="x_name" value="$[name]">
<set name="x_address1" value="$[address1]">
<set name="x_address2" value="$[address2]">
<set name="x_contact" value="$[contact]">
<sql>
insert into contractors
set name='$[x_name]',
created=now(),
owner=$[@_login_id],
address1='$[x_address1]',
address2='$[x_address2]',
city='$[city]',
state='$[state]',
zip_code='$[zip_code]',
contact='$[x_contact]',
contact_phone='$[contact_phone]',
contact_email='$[contact_email]'
</sql>$[sqlerror]
</process>
@@ -0,0 +1,14 @@
<page>
<title>Quality Iron - Create Customer</title>
<contents>
<div>
<h1>CREATE CUSTOMER</h1>
<div>
<table>
<include file="qualityiron-site/customer.form">
</table>
</div>
<abutton process="createcustomer" page="customers">Create Customer</abutton>
</div>
</contents>
</page>
@@ -0,0 +1,9 @@
<process>
<set name="x_name" value="$[name]">
<sql>
insert into customers
set name='$[x_name]',
created=now(),
owner=$[@_login_id]
</sql>$[sqlerror]
</process>
@@ -0,0 +1,4 @@
<process>
<set name="x_description" value="$[new_role_description]">
<sql>insert into roles set description='$[x_description]'</sql>$[sqlerror]
</process>
@@ -0,0 +1,6 @@
<process>
<set name="x_description" value="$[new_status_description]">
<set name="x_comment" value="$[new_status_comment]">
<set name="x_sequence" value="$[new_status_sequence]">
<sql>insert into status set description='$[x_description]', comment='$[x_comment]', sequence=$[x_sequence]</sql>$[sqlerror]
</process>
@@ -0,0 +1,4 @@
<process>
<set name="x_description" value="$[new_subtype_description]">
<sql>insert into subtype set type_id=$[new_subtype_type_id], description='$[x_description]'</sql>$[sqlerror]
</process>
@@ -0,0 +1,4 @@
<process>
<set name="x_description" value="$[new_type_description]">
<sql>insert into type set description='$[x_description]'</sql>$[sqlerror]
</process>
+14
View File
@@ -0,0 +1,14 @@
<page>
<title>Quality Iron - Create User</title>
<contents>
<div>
<h1>CREATE USER</h1>
<div>
<table>
<include file="qualityiron-site/user.form">
</table>
</div>
<abutton process="createuser" page="users">Create User</abutton>
</div>
</contents>
</page>
+11
View File
@@ -0,0 +1,11 @@
<process>
<set name="x_username" value="$[username]">
<set name="x_email" value="$[email]">
<sql>
insert into users
set name='$[x_username]',
secret='$[secret]',
email='$[x_email]',
phone='$[phone]'
</sql>$[sqlerror]
</process>
+7
View File
@@ -0,0 +1,7 @@
<div class="card">
<table>
<tr><th>Name:</th><td>$[name]</td></tr>
<tr><th>Created:</th><td>$[created_date]</td></tr>
<tr><th>Owner:</th><td>$[owner_name]</td></tr>
</table>
</div>
+1
View File
@@ -0,0 +1 @@
<tr><td>Customer Name:</td><td><input type="text" name="name" size="100" value="$[name]"></td></tr>
+61
View File
@@ -0,0 +1,61 @@
<page>
<title>Quality Iron - Customer</title>
<contents>
<sql>
select customers.*,
date_format(convert_tz(created,'UTC','America/Los_Angeles'), "%W, %M %D, %Y %l:%i%p") as created_date,
users.name as owner_name
from customers
join users on customers.owner=users.id
where customers.id=$[@_selected_customer_id]
</sql>$[sqlerror]
<h1>CUSTOMER ($[.name])</h1>
<linkbutton page="editcustomer">Edit</linkbutton>
<set name="name" value="$[.name]">
<set name="created_date" value="$[.created_date]">
<set name="owner_name" value="$[.owner_name]">
<include file="qualityiron-site/customer.card">
<retain name="selected_job_id">
<retain name="selected_contractor_id">
<div>
<h1>JOBS</h1>
<div style="padding: 5px;">
<sql>
select *,
customers.name as customer,
contractors.name as contractor
from jobs
join customers on jobs.customer_id=customers.id
join contractors on jobs.contractor_id=contractors.id
join status on jobs.status_id=status.id
where customer_id=$[@_selected_customer_id]
order by contractor</sql>$[sqlerror]
<ifrow>
<div style="display: inline-block;">Jobs</div>
<div>
<table id="list">
<tr>
<th></th>
<th>Job Number</th>
<th>Contractor</th>
<th>Insurance</th>
<th>Status</th>
</tr>
<whilerow>
<tr style="visibility: table-row">
<td><linkbutton page="job" process="selectjob" name="selected_job_id" value="$[.id]">Open</linkbutton></td>
<td>$[.job_number]</td>
<td>$[.contractor] <linkbutton page="contractor" process="selectcontractor" name="selected_contractor_id" value="$[.contractor_id]"><img src="/assets/open.png" align="right"></linkbutton></td>
<td>$[.insurance]</td>
<td>$[.description]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</div>
</contents>
</page>
+58
View File
@@ -0,0 +1,58 @@
<page>
<title>Quality Iron</title>
<contents>
<script>
function setrows(include) {
var table = document.getElementById("list");
for (var i = 1; row = table.rows[i]; i++) {
if(include == "") {
row.style.visibility = "visible";
} else {
row.style.visibility = "collapse";
}
for (var j = 0; col = row.cells[j]; j++) {
if(col.innerHTML.toUpperCase().includes(include.toUpperCase())) {
row.style.visibility = "visible";
}
}
}
}
</script>
<retain name="selected_customer_id">
<div>
<h1>CUSTOMERS</h1>
<div style="padding: 5px;">
<div style="display: inline-block;"><linkbutton page="createcustomer">Create Customer</linkbutton></div>
<sql>
select *,
date_format(convert_tz(created,'UTC','America/Los_Angeles'), "%W, %M %D, %Y %l:%i%p") as created_date
from customers
order by name</sql>$[sqlerror]
<ifrow>
<div style="display: inline-block;">Customers</div>
<div style="border-radius: 5px; display: inline-block; background: #345; color: #def; margin-left: 20px; padding: 5px;">
<img style="margin-top: 3px;" src="/assets/magglass.png" width="20px;" align="top">
<input style="font-size: 20px; color: #def;" type="text" size="10" name="search" value="" onkeyup="setrows(this.value); return true;">
</div>
</div>
<div>
<table id="list">
<tr>
<th></th>
<th>Name</th>
<th>Created</th>
</tr>
<whilerow>
<tr style="visibility: table-row">
<td><linkbutton page="customer" process="selectcustomer" name="selected_customer_id" value="$[.id]">Open</linkbutton></td>
<td>$[.name]</td>
<td>$[.created_date]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</contents>
</page>
@@ -0,0 +1,3 @@
<process>
<sql>delete from job_addresses where id=$[selected_job_address_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,3 @@
<process>
<sql>delete from job_contacts where id=$[selected_job_contact_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,3 @@
<process>
<sql>delete from roles where id=$[selected_role_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,3 @@
<process>
<sql>delete from status where id=$[selected_status_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,3 @@
<process>
<sql>delete from subtype where id=$[selected_subtype_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,3 @@
<process>
<sql>delete from type where id=$[selected_type_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,3 @@
<process>
<sql>delete from users where id=$[@_selected_user_id]</sql>$[sqlerror]
</process>
+36
View File
@@ -0,0 +1,36 @@
<page>
<title>Quality Iron</title>
<contents>
<div id="view" style="width: 100%; height: 80%; border: 2px solid #456;">
<img src="/assets/testing-3.png">
</div>
<script>
function mousemove(e) {
mouseX = e.clientX;
mouseY = e.clientY;
if(e.buttons == 1) {
translateX += e.movementX;
translateY += e.movementY;
view.style.transform = `translate(${translateX}px,${translateY}px) scale(${scale})`;
}
e.preventDefault();
}
function zoom(e) {
scale += e.deltaY * -0.001;
view.style.transform = `translate(${translateX}px,${translateY}px) scale(${scale})`;
view.style.transformOrigin = `${mouseX}px ${mouseY}px`;
e.preventDefault();
}
var scale = 0.5;
var mouseX = 0;
var mouseY = 0;
var translateX = 0;
var translateY = 0;
const view = document.getElementById('view');
view.onwheel = zoom;
view.onmousemove = mousemove;
view.style.transform = `scale(${scale})`;
view.style.overflow = 'hidden';
</script>
</contents>
</page>
@@ -0,0 +1,26 @@
<page>
<title>Quality Iron - Edit Contractor</title>
<contents>
<div>
<h1>EDIT CONTRACTOR</h1>
<sql>select * from contractors where id=$[@_selected_contractor_id]</sql>$[sqlerror]
<div>
<table>
<set name="name" value="$[.name]">
<set name="address1" value="$[.address1]">
<set name="address2" value="$[.address2]">
<set name="city" value="$[.city]">
<set name="state" value="$[.state]">
<set name="zip_code" value="$[.zip_code]">
<set name="contact" value="$[.contact]">
<set name="contact_phone" value="$[.contact_phone]">
<set name="contact_email" value="$[.contact_email]">
<set name="created" value="$[.created]">
<set name="owner" value="$[.owner]">
<include file="qualityiron-site/contractor.form">
</table>
</div>
<abutton process="updatecontractor" page="contractor">Update Contractor</abutton>
</div>
</contents>
</page>
@@ -0,0 +1,18 @@
<page>
<title>Quality Iron - Edit Customer</title>
<contents>
<div>
<h1>EDIT CUSTOMER</h1>
<sql>select * from customers where id=$[@_selected_customer_id]</sql>$[sqlerror]
<div>
<table>
<set name="name" value="$[.name]">
<set name="created" value="$[.created]">
<set name="owner" value="$[.owner]">
<include file="qualityiron-site/customer.form">
</table>
</div>
<abutton process="updatecustomer" page="customer">Update Customer</abutton>
</div>
</contents>
</page>
@@ -0,0 +1,43 @@
<page>
<title>Quality Iron - Document Types</title>
<contents>
<retain name="selected_type_id">
<retain name="selected_subtype_id">
<h1>MANAGE DOCUMENT TYPES/SUBTYPES</h1>
<database host="$[host]" name="$[database]" user="$[user]" password="$[password]" sessionid="2">
<sql>select * from type order by description</sql>$[sqlerror]
<whilerow>
<div style="background-color: #89a; width: 400px; padding: 10px; margin-bottom: 10px;">
<div>
<input type="text" name="typedescription$[.id]" size="20" value="$[.description]">
<linkbutton process="updatetype" name="selected_type_id" value="$[.id]">Save</linkbutton>
<linkbutton process="deletetype" name="selected_type_id" value="$[.id]"><img width="18" src="/assets/delete.png"></linkbutton>
</div>
<set name="tid" value="$[.id]">
<table>
<sql sessionid="2">select s.*,
(select count(*) from documents d where d.subtype_id=s.id) as count
from subtype s where s.type_id=$[tid] order by description</sql>$[sqlerror]
<whilerow sessionid="2">
<tr>
<td><input type="text" name="subtypedescription$[.id]" size="15" value="$[.description]"></td>
<td>$[.count]</td>
<td><linkbutton process="updatesubtype" name="selected_subtype_id" value="$[.id]">Save</linkbutton></td>
<td>
<if value1="$[.count]" value2="0" type="eq">
<linkbutton process="deletesubtype" name="selected_subtype_id" value="$[.id]"><img width="18" src="/assets/delete.png"></linkbutton>
</if>
</td>
</tr>
</whilerow>
</table>
<input type="text" name="new_subtype_description" size="15" value="">
<linkbutton process="createsubtype" name="new_subtype_type_id" value="$[.id]">Add Subtype</linkbutton>
</div>
</whilerow>
<h2>Add Document Type</h2>
<input type="text" name="new_type_description" size="20" value="">
<abutton process="createtype">Add Type</abutton>
</database>
</contents>
</page>
+40
View File
@@ -0,0 +1,40 @@
<page>
<title>Quality Iron - Status Values</title>
<contents>
<retain name="selected_status_id">
<h1>STATUS VALUES</h1>
<sql>select s.*,
(select count(*) from jobs where status_id=s.id) as count
from status s
order by sequence</sql>$[sqlerror]
<table id="status_table">
<tr>
<th></th>
<th style="text-align: left;">Description</th>
<th style="text-align: left;">Comment</th>
<th style="text-align: left;">Sequence</th>
<th style="text-align: left;">Used</th>
<th></th>
</tr>
<whilerow>
<tr>
<td>
<if value1="$[.count]" value2="0" type="eq">
<linkbutton process="deletestatus" name="selected_status_id" value="$[.id]"><img width="18" style="cursor: pointer;" src="/assets/delete.png"></linkbutton>
</if>
</td>
<td><input type="text" name="description$[.id]" size="20" value="$[.description]"></td>
<td><input type="text" name="comment$[.id]" size="40" value="$[.comment]"></td>
<td><input type="text" name="sequence$[.id]" size="4" value="$[.sequence]"></td>
<td>$[.count]</td>
<td><linkbutton process="updatestatus" name="selected_status_id" value="$[.id]">Save</linkbutton></td>
</tr>
</whilerow>
</table>
<h2>Add Status Value</h2>
<input type="text" name="new_status_description" size="20" value="">
<input type="text" name="new_status_comment" size="40" value="">
<input type="text" name="new_status_sequence" size="4" value="">
<abutton process="createstatus">Add</abutton>
</contents>
</page>
+23
View File
@@ -0,0 +1,23 @@
<page>
<title>Quality Iron - Edit User</title>
<contents>
<div>
<h1>EDIT USER</h1>
<sql>
select * from users where id=$[@_selected_user_id]
</sql>$[sqlerror]
<div style="width: 800px;">
<table>
<set name="username" value="$[.name]">
<set name="secret" value="$[.secret]">
<set name="email" value="$[.email]">
<set name="phone" value="$[.phone]">
<set name="allow_user_maint" value="$[.allow_user_maint]">
<include file="qualityiron-site/user.form">
</table>
<abutton process="updateuser" page="users">Update User</abutton>
<div style="float: right;"><abutton process="deleteuser" page="users">Delete User</abutton></div>
</div>
</div>
</contents>
</page>
+6
View File
@@ -0,0 +1,6 @@
<page>
<title>Quality Iron - Email</title>
<contents>
<iframe src="https://mail.qualityiron.vegas" style="width: 100%; height: 85vh; border: none;"></iframe>
</contents>
</page>
+29
View File
@@ -0,0 +1,29 @@
<tag name="tab" keywords="page">
<td class="baritem<if value1="$[PAGE]" value2="#[page]" type="eq">selected</if>">
<linkbutton page="#[page]"><container></linkbutton></td>
<td style="border-bottom: 1pt solid #bbb;">&nbsp;</td>
</tag>
<if value1="$[_login_id]" value2="" type="ne">
<sql>select * from users where id=$[_login_id]</sql>
</if>
<table class="menubar" cellspacing="0" cellpadding="0" style="width: 100%">
<tr>
<td style="border-bottom: 1pt solid #bbb; width: 20px;">&nbsp;</td>
<tab page="home"><a href="/home">HOME</a></tab>
<tab page="jobs"><a href="/jobs">JOBS</a></tab>
<tab page="contractors"><a href="/contractors">CONTRACTORS</a></tab>
<tab page="customers"><a href="/customers">CUSTOMERS</a></tab>
<tab page="library"><a href="/library">LIBRARY</a></tab>
<tab page="profile"><a href="/profile">MY PROFILE</a></tab>
<td style="float: right; margin: 2px;"><a target="qiemail" href="https://mail.qualityiron.vegas"><button type="button">E-MAIL</button></a></td>
<if value1="$[_login_id]" value2="" type="ne">
<ifrow>
<if value1="$[.allow_user_maint]" value2="Y" type="eq">
<tab page="admin"><a href="/admin">ADMIN</a></tab>
</if>
</ifrow>
</if>
<td style="border-bottom: 1pt solid #bbb; width: 10px;">&nbsp;</td>
</tr>
</table>
+125
View File
@@ -0,0 +1,125 @@
<page>
<title>Quality Iron - Home</title>
<script>
function rowhover(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DDC';
td.style.cursor = 'pointer';
}
}
function rowout(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DEF';
td.style.cursor = 'default';
}
}
function goto(id) {
document.forms[0].PAGE.value = 'job';
document.forms[0].PROCESS.value = 'selectjob';
document.forms[0].selected_job_id.value = id;
document.forms[0].requestSubmit();
}
</script>
<contents>
<div>
<h1>HOME</h1>
<include file="qualityiron-site/jobs.list">
<div>
<h2>Job Notes</h2>
<sql>select *,
date_format(convert_tz(jn.created,'UTC','America/Los_Angeles'),'%W, %M %D, %Y at %l:%i:%s %p') as formatted_date
from job_notation jn
join users u on jn.owner=u.id
join jobs j on jn.job_id=j.id
order by jn.created desc limit 5
</sql>$[sqlerror]
<table style="width: 700px;">
<whilerow>
<tr><th style="text-align: left;">Created $[.formatted_date] by $[.name]</th></tr>
<tr>
<td class="note_job">Job Number: <b>$[.job_number] $[.job_name]</b></td></tr>
<tr onmouseenter="rowhover(this);" onmouseleave="rowout(this);" onclick="goto('$[.job_id]');"><td>$[.notation]</td></tr>
</whilerow>
</table>
<br>
<h2>Job Activity</h2>
<sql>select *,
date_format(convert_tz(job_activity_log.created,'UTC','America/Los_Angeles'),'%W, %M %D, %Y at %l:%i:%s %p') as log_date,
users.name as user_name,
jobs.job_name as job_name,
jobs.id as job_id
from job_activity_log
join users on job_activity_log.user_id=users.id
join jobs on job_activity_log.job_id=jobs.id
order by job_activity_log.created desc limit 15
</sql>$[sqlerror]
<table>
<tr>
<th>Date</th>
<th>User</th>
<th>Job Name</th>
<th>Activity</th>
</tr>
<whilerow>
<tr onmouseenter="rowhover(this);" onmouseleave="rowout(this);" onclick="goto('$[.job_id]');">
<td>$[.log_date]</td>
<td>$[.user_name]</td>
<td>$[.job_name]</td>
<td>$[.text]</td>
</tr>
</whilerow>
</table>
<br>
<h2>Job Reviews</h2>
<sql>select *,
date_format(review_date,'%W, %M %D, %Y') as formatted_date,
j.id as job_id,
j.job_name as job_name,
co.name as contractor_name,
cu.name as customer_name,
if((lag(review_date) over (order by review_date))=review_date,0,1) as changed,
if(datediff(review_date,now())=0,'#798;',if(datediff(review_date,now())<1,'#534','#354')) as date_color
from job_reviews jr
join jobs j on jr.job_id=j.id
join contractors co on j.contractor_id=co.id
left outer join customers cu on j.customer_id=cu.id
where jr.owner=$[_login_id]
order by review_date
</sql>$[sqlerror]
<ifrow>
<table>
<tr>
<th>Notation</th>
<th>Job Number</th>
<th>Job Name</th>
<th>Contractor</th>
<th>Contractor Job Id</th>
</tr>
<whilerow>
<if value1="$[.changed]" value2="1" type="eq">
<tr><td colspan="5" style="font-weight: bold; background: $[date_color]; color: #fff;">$[formatted_date]</td></tr>
</if>
<tr style="visibility: table-row" onmouseenter="rowhover(this);" onmouseleave="rowout(this);" onclick="goto('$[.job_id]');">
<td>$[.notation]</td>
<td>$[.job_number]</td>
<td>$[.job_name]</td>
<td>$[.contractor_name]</td>
<td>$[.contractor_job_id]</td>
</tr>
</whilerow>
</table>
<else>
No reviews set.
</ifrow>
</div>
</div>
</contents>
</page>
+29
View File
@@ -0,0 +1,29 @@
<div class="sider" style="width: 100%; border: 1pt solid #000; vertical-align: top;">
<h2>Job Notes</h2>
<sql>select *,
date_format(convert_tz(created,'UTC','America/Los_Angeles'),'%W, %M %D, %Y at %l:%i:%s %p') as formatted_date
from job_notation jn
join users u on jn.owner=u.id
where job_id=$[@_selected_job_id]
</sql>$[sqlerror]
<table style="width: 100%;">
<whilerow>
<tr><th style="text-align: left;">Created $[.formatted_date] by $[.name]</th></tr>
<tr><td>$[.notation]</td></tr>
</whilerow>
</table>
<div>
<textarea id="note" style="width: 100%; height: 80px;" name="job_notation"></textarea>
<script>
if (window.CKEDITOR) {
if (CKEDITOR.instances.note) {
CKEDITOR.instances.note.destroy(true);
}
CKEDITOR.replace('note');
}
</script>
<div>
<button onclick="if(window.CKEDITOR && CKEDITOR.instances.note){CKEDITOR.instances.note.updateElement();} document.forms[0].PAGE.value='job'; document.forms[0].PROCESS.value='addjobnotation'; document.forms[0].requestSubmit();">Add Notation</button>
</div>
</div>
</div>
+268
View File
@@ -0,0 +1,268 @@
<page>
<title>Quality Iron - Job</title>
<contents>
<script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
<script>
function rowhover(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DDC';
td.style.cursor = 'pointer';
}
}
function rowout(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DEF';
td.style.cursor = 'default';
}
}
function goto(id) {
document.forms[0].PAGE.value = 'job';
document.forms[0].PROCESS.value = 'selectjob';
document.forms[0].selected_job_id.value = id;
document.forms[0].requestSubmit();
}
</script>
<if value1="$[message]" value2="" type="ne">
<div style="background-color: #f88; padding: 3px; font-weight: bold;">
$[message]
</div>
</if>
<sql>
select *,
date_format(convert_tz(jobs.created, 'UTC','America/Los_Angeles'), "%W, %M %D, %Y %l:%i%p") as created_date,
status.description as status,
customers.name as customer_name,
contractors.name as contractor_name
from jobs
left outer join customers on jobs.customer_id=customers.id
left outer join contractors on jobs.contractor_id=contractors.id
join status on status_id=status.id
where jobs.id=$[@_selected_job_id]
</sql>$[sqlerror]
<div style="background-color: #CDE; display: inline-block; margin-left: 5px; padding: 3px 10px 3px 10px; border-radius: 7px 7px 0px 0px; border: 1pt outset #678;">JOB ($[.job_name] $[.job_number])</div>
<linkbutton page="jobdocs"><div style="background-color: #ABC; display: inline-block; margin-left: 5px; padding: 3px 10px 3px 10px; border-radius: 7px 7px 0px 0px; border: 1pt outset #678;">DOCUMENTS</div></linkbutton>
<table style="border: 0px solid #000;"><tr><td style="width: 34%; vertical-align: top; background-color: #ABC;">
<if value1="$[message]" value2="" type="eq">
<div class="sider" style="vertical-align: top; width: 100%;">
<set name="jobnumber" value="$[.job_number]">
<set name="job_name" value="$[.job_name]">
<set name="customer_id" value="$[.customer_id]">
<set name="customer_name" value="$[.customer_name]">
<set name="created" value="$[.created]">
<set name="created_by" value="$[.created_by]">
<set name="contractor_id" value="$[.contractor_id]">
<set name="contractor_name" value="$[.contractor_name]">
<set name="contractor_job_id" value="$[.contractor_job_id]">
<set name="apn" value="$[.apn]">
<set name="insurance" value="$[.insurance]">
<set name="status_id" value="$[.status_id]">
</if>
<include file="qualityiron-site/jobfolder.form">
</div>
<script>
function shownewaddressform() {
document.getElementById('addnewaddress').style.display='block';
}
</script>
<div class="sider" style="border: 1pt solid #000; vertical-align: top; width: 100%;">
<h2>Job Addresses <div style="padding: 2px; display: inline-block; float: right; cursor: pointer;"><img width="18" onclick="shownewaddressform();" style="float: right;" src="/assets/plus.png"></div></h2>
<div>
<sql>select * from address_types</sql>
<div id="addnewaddress" style="display: none;">
<table style="width: 100%;">
<tr><th style="width: 30%;">Address Type:</th><td><select name="address_type">
<whilerow>
<option value="$[.id]">$[.description]</option>
</whilerow>
</select></td></tr>
<tr><th>Address 1:</th><td><input type="text" name="address1"></td></tr>
<tr><th>Address 2:</th><td><input type="text" name="address2"></td></tr>
<tr><th>City:</th><td><input type="text" name="city"></td></tr>
<tr><th>State:</th><td><input type="text" name="state"></td></tr>
<tr><th>Zip Code:</th><td><input type="text" name="zip_code"></td></tr>
</table>
<abutton process="addjobaddress">Add Address</abutton>
</div>
<retain name="selected_job_address_id">
<sql>select *,
ja.id as job_address_id
from addresses a
join job_addresses ja on ja.address_id=a.id
join address_types at on ja.address_type=at.id
where ja.job_id=$[@_selected_job_id]
</sql>
<ifrow>
<whilerow>
<div style="padding: 2px;">
<table style="width: 100%;">
<tr><th style="width: 30%;">Address Type:</th><td>$[.description]<linkbutton process="deletejobaddress" name="selected_job_address_id" value="$[.job_address_id]"><img width="18" style="float: right;" src="/assets/delete.png"></linkbutton></td></tr>
<tr><th>Address 1:</th><td style="width: 180px;">$[.address1]</td></tr>
<tr><th>Address 2:</th><td style="width: 180px;">$[.address2]</td></tr>
<tr><th>City:</th><td>$[.city]</td></tr>
<tr><th>State:</th><td>$[.state]</td></tr>
<tr><th>Zip Code:</th><td>$[.zip_code]</td></tr>
</table>
</div>
</whilerow>
<else>
<p style="text-align: center;">No address exists for this job.</p>
</ifrow>
</div>
</div>
</td><td style="width: 33%; vertical-align: top; background-color: #ABC;">
<script>
function shownewcontactsform() {
document.getElementById('addnewcontact').style.display='block';
}
</script>
<div class="sider" style="border: 1pt solid #000; width: 100%; vertical-align: top;">
<h2>Job Contacts <div style="padding: 2px; display: inline-block; float: right; cursor: pointer;"><img width="18" onclick="shownewcontactsform();" style="float: right;" src="/assets/plus.png"></div></h2>
<div>
<sql>select * from contact_types</sql>
<div id="addnewcontact" style="display: none;">
<table style="width: 100%;">
<tr><th style="width: 30%;">Contact Type:</th><td><select name="contact_type">
<whilerow>
<option value="$[.id]">$[.description]</option>
</whilerow>
</select></td></tr>
<sql>select * from contacts</sql>
<tr><th>Name:</th><td style="width: 180px;"><input list="contacts" name="contact_name" id="contact_name">
<datalist id="contacts">
<script>
var contact_name = document.getElementById('contact_name');
contact_name.addEventListener('change', (e) => {
var option = document.querySelector('option[value="' + e.target.value.trim() + '"]');
document.getElementById('phonex').value = option.phone;
document.getElementById('emailx').value = option.email;
});
var contacts = document.getElementById('contacts');
<whilerow>
var option = document.createElement('option');
option.setAttribute('value','$[.name]');
option.phone = '$[.phone]';
option.email = '$[.email]';
contacts.appendChild(option);
</whilerow>
</script>
</datalist></td></tr>
<tr><th>Phone:</th><td><input type="tel" name="phonex" id="phonex"></td></tr>
<tr><th>Email:</th><td><input type="email" name="emailx" id="emailx"></td></tr>
</table>
<abutton process="addjobcontact">Add Contact</abutton>
</div>
<retain name="selected_job_contact_id">
<sql>select *,
jc.id as job_contact_id
from contacts c
join job_contacts jc on jc.contact_id=c.id
join contact_types ct on jc.contact_type=ct.id
where job_id=$[@_selected_job_id]
</sql>
<ifrow>
<whilerow>
<div style="padding: 2px;">
<table style="width: 100%;">
<tr><th style="width: 30%;">Contact Type:</th><td>$[.description]<linkbutton process="deletejobcontact" name="selected_job_contact_id" value="$[.job_contact_id]"><img width="18" style="float: right;" src="/assets/delete.png"></linkbutton></td></tr>
<tr><th>Name:</th><td style="width: 180px;">$[.name]</td></tr>
<tr><th>Phone:</th><td>$[.phone]</td></tr>
<tr><th>Email:</th><td>$[.email]</td></tr>
</table>
</div>
</whilerow>
<else>
<p style="text-align: center;">No contact exists for this job.</p>
</ifrow>
</div>
</div>
</td><td style="width: 33%; vertical-align: top; background-color: #9AB;">
<div class="sider" style="border: 1pt solid #000; width: 100%; vertical-align: top;">
<h2>Job Dates</h2>
<sql>select *,
dt.id as date_type_id
from date_types dt
left outer join job_dates jd on jd.type=dt.id and jd.job_id=$[@_selected_job_id]
order by description</sql>$[sqlerror]
<table style="width: 100%;">
<whilerow>
<tr><th style="width: 50%;">$[.description]:</th><td><input type="date" name="date$[.date_type_id]" value="$[.date]"></td></tr>
</whilerow>
<td colspan="2"><abutton process="updatejobdates">Update Dates</abutton></td>
</table>
</div>
<div class="sider" style="border: 1pt solid #000; width: 100%; vertical-align: top; margin-top: 3px;">
<h2>Reviews</h2>
<sql>select *
from job_reviews
where owner=$[@_login_id]
and job_id=$[@_selected_job_id]
order by review_date</sql>
<whilerow>
<table style="width: 100%;">
<tr><th style="width: 30%;">Review Date:</th><td>$[.review_date]</td></tr>
<tr><th>Reason:</th><td>$[.notation]</td></tr>
</table>
</whilerow>
<table style="width: 100%;">
<tr><th style="width: 30%;">Review Date:</th><td><input type="date" name="review_date"></td></tr>
<tr><th>Reason:</th><td><textarea name="notation" style="width: 100%;"></textarea></td></tr>
<td colspan="2"><abutton process="setreview">Set Review</abutton></td>
</table>
</div>
</td></tr>
<tr><td colspan="2" style="vertical-align: top; background-color: #9AB;">
<include file="qualityiron-site/job.notations">
</td><td style="vertical-align: top; background-color: #9AB;">
<div class="sider" style="border: 1pt solid #000; width: 100%; vertical-align: top;">
<h2>Job Activity</h2>
<sql>select *,
date_format(convert_tz(job_activity_log.created,'UTC','America/Los_Angeles'),'%W, %M %D, %Y at %l:%i:%s %p') as log_date,
users.name as user_name,
jobs.job_name as job_name,
jobs.id as job_id
from job_activity_log
join users on job_activity_log.user_id=users.id
join jobs on job_activity_log.job_id=jobs.id
where jobs.id = $[@_selected_job_id]
order by job_activity_log.created desc limit 15
</sql>$[sqlerror]
<table>
<tr>
<th>Date</th>
<th>User</th>
<th>Job Name</th>
<th>Activity</th>
</tr>
<whilerow>
<tr onmouseenter="rowhover(this);" onmouseleave="rowout(this);" onclick="goto('$[.job_id]');">
<td>$[.log_date]</td>
<td>$[.user_name]</td>
<td>$[.job_name]</td>
<td>$[.text]</td>
</tr>
</whilerow>
</table>
</div>
</td></tr></table>
</contents>
</page>
+2
View File
@@ -0,0 +1,2 @@
#api GET /jobdocs/download
<if expr="locate('/jobdocs/download','$[REQUEST_URI]') = 1"><if value1="$[@_login_id]" value2="" type="eq">Not authorized.<else><set name="host" value="localhost"><set name="database" value="qualityiron"><set name="user" value="barant"><set name="password" value="uversa1960"><database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid=""><sql sessionid="">select id,name,filename,mimetype from documents where id=$[id] and status='ACTIVE'</sql><ifrow sessionid=""><set name="dl_name" value="$[.name]"><set name="dl_filename" value="$[.filename]"><set name="dl_mimetype" value="$[.mimetype]"><header name="Content-Type" value="$[dl_mimetype]"><header name="Content-Disposition" value="attachment; filename=$[dl_name]"><read file="./documents-qualityiron-site/$[dl_filename]" name="_filedata">$[_filedata]<else>Document not found.</ifrow></database></if><else>Unknown route.</if>
+133
View File
@@ -0,0 +1,133 @@
<page>
<title>Quality Iron - Job Documents</title>
<contents>
<sql>select job_number, job_name from jobs where id=$[@_selected_job_id]</sql>$[sqlerror]
<linkbutton page="job"><div style="background-color: #ABC; display: inline-block; margin-left: 5px; padding: 3px 10px 3px 10px; border-radius: 7px 7px 0px 0px; border: 1pt outset #678;">JOB ($[.job_name] $[.job_number])</div></linkbutton>
<div style="background-color: #CDE; display: inline-block; margin-left: 5px; padding: 3px 10px 3px 10px; border-radius: 7px 7px 0px 0px; border: 1pt outset #678;">DOCUMENTS</div>
<div style="padding: 10px; background: #fff;">
<h2>Upload Document</h2>
<div>
Category:
<select id="jobdocs-subtype">
<sql>select type.description as title, subtype.id as id, subtype.description as description
from type join subtype on subtype.type_id=type.id
order by type.description, subtype.description</sql>$[sqlerror]
<set name="_jd_last" value="">
<whilerow>
<if value1="$[_jd_last]" value2="$[.title]" type="ne">
<if value1="$[_jd_last]" value2="" type="ne"></optgroup></if>
<optgroup label="$[.title]">
<set name="_jd_last" value="$[.title]">
</if>
<option value="$[.id]">$[.description]</option>
</whilerow>
<if value1="$[_jd_last]" value2="" type="ne"></optgroup></if>
</select>
</div>
<input type="file" id="jobdocs-file-input" multiple style="display:none;">
<div id="jobdocs-dropzone">Drop files here, or click to choose files to upload</div>
<div id="jobdocs-list-body"><div id="jobdocs-empty">Loading&hellip;</div></div>
</div>
<script>
(function() {
var jobId = '$[@_selected_job_id]';
var dropzone = document.getElementById('jobdocs-dropzone');
var fileInput = document.getElementById('jobdocs-file-input');
var subtypeSelect = document.getElementById('jobdocs-subtype');
var listBody = document.getElementById('jobdocs-list-body');
if (!dropzone || !listBody) return;
function escapeHtml(s) {
var div = document.createElement('div');
div.textContent = s == null ? '' : String(s);
return div.innerHTML;
}
function post(path, params) {
return fetch(path, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(params || {}).toString()
}).then(function(r) { return r.json(); });
}
function formatSize(bytes) {
if (bytes > 1048576) return (bytes / 1048576).toFixed(1) + ' MB';
if (bytes > 1024) return (bytes / 1024).toFixed(1) + ' KB';
return bytes + ' B';
}
function loadList() {
post('/jobdocs/api/list', { job_id: jobId }).then(function(res) {
if (!res.ok || !res.documents.length) {
listBody.innerHTML = '<div id="jobdocs-empty">No documents yet - upload your first one above.</div>';
return;
}
var html = '<table id="jobdocs-list"><tr><th>Type</th><th>Name</th><th>Size</th><th>Uploaded</th><th>By</th><th></th><th></th></tr>';
for (var i = 0; i < res.documents.length; i++) {
var doc = res.documents[i];
html += '<tr>' +
'<td>' + escapeHtml(doc.subtype || doc.type || '') + '</td>' +
'<td>' + escapeHtml(doc.name) + '</td>' +
'<td>' + formatSize(doc.file_size) + '</td>' +
'<td>' + escapeHtml(doc.submitted_date) + '</td>' +
'<td>' + escapeHtml(doc.submitted_by) + '</td>' +
'<td><span class="jobdocs-action" data-action="download" data-id="' + doc.id + '" data-name="' + escapeHtml(doc.name) + '">Download</span></td>' +
'<td><span class="jobdocs-action" data-action="delete" data-id="' + doc.id + '">Delete</span></td>' +
'</tr>';
}
html += '</table>';
listBody.innerHTML = html;
var actions = listBody.querySelectorAll('.jobdocs-action');
for (var j = 0; j < actions.length; j++) {
actions[j].addEventListener('click', function() {
var id = this.getAttribute('data-id');
if (this.getAttribute('data-action') === 'download') {
window.fileManagerDownload && window.fileManagerDownload(id, this.getAttribute('data-name'));
} else {
post('/jobdocs/api/delete', { id: id }).then(function(res) {
if (res.ok) loadList();
});
}
});
}
}).catch(function() {
listBody.innerHTML = '<div id="jobdocs-empty">Could not load documents.</div>';
});
}
function uploadFiles(files) {
if (!files || !files.length) return;
if (window.fileManagerUpload)
window.fileManagerUpload(files, jobId, subtypeSelect.value);
}
dropzone.addEventListener('click', function() { fileInput.click(); });
fileInput.addEventListener('change', function() {
uploadFiles(fileInput.files);
fileInput.value = '';
});
dropzone.addEventListener('dragover', function(e) {
e.preventDefault();
dropzone.classList.add('jobdocs-dropzone-active');
});
dropzone.addEventListener('dragleave', function() {
dropzone.classList.remove('jobdocs-dropzone-active');
});
dropzone.addEventListener('drop', function(e) {
e.preventDefault();
dropzone.classList.remove('jobdocs-dropzone-active');
uploadFiles(e.dataTransfer.files);
});
document.addEventListener('jobdocs:changed', loadList);
loadList();
})();
</script>
</contents>
</page>
+84
View File
@@ -0,0 +1,84 @@
#api POST /jobdocs/api/upload
#api POST /jobdocs/api/delete
#api POST /jobdocs/api/list
<set name="host" value="localhost">
<set name="database" value="qualityiron">
<set name="user" value="barant">
<set name="password" value="uversa1960">
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="">
<if value1="$[REQUEST_URI]" value2="/jobdocs/api/upload" type="eq">
<header name="Content-Type" value="application/json">
<if value1="$[@_login_id]" value2="" type="eq">
{"ok":false,"error":"Not authorized."}
<else>
<if value1="$[name]" value2="" type="eq">
{"ok":false,"error":"Name is required."}
<else>
<if value1="$[job_id]" value2="" type="eq">
{"ok":false,"error":"job_id is required."}
<else>
<set name="x_name" value="$[name]">
<set name="x_mimetype" value="$[mimetype]">
<sql sessionid="">select uuid() as u</sql>$[sqlerror]
<set name="storage_name" value="$[.u]">
<sql sessionid="">insert into documents
set name='$[x_name]',
subtype_id=$[subtype_id],
owner=$[@_login_id],
submitted_by=$[@_login_id],
submitted_date=now(),
job_id=$[job_id],
filename='$[storage_name]',
mimetype='$[x_mimetype]',
file_size=$[file_size],
status='ACTIVE'</sql>$[sqlerror]
<sql sessionid="">select last_insert_id() as document_id</sql>$[sqlerror]
<set name="document_id" value="$[.document_id]">
<write file="./documents-qualityiron-site/$[storage_name]" mode="overwrite" value="$[filedata]">
{"ok":true,"id":$[document_id],"name":"$[x_name]"}
</if>
</if>
</if>
<else>
<if value1="$[REQUEST_URI]" value2="/jobdocs/api/delete" type="eq">
<header name="Content-Type" value="application/json">
<if value1="$[@_login_id]" value2="" type="eq">
{"ok":false,"error":"Not authorized."}
<else>
<sql sessionid="">select id from documents where id=$[id] and status='ACTIVE'</sql>$[sqlerror]
<ifrow sessionid="">
<sql sessionid="">update documents set status='DELETED' where id=$[id]</sql>$[sqlerror]
{"ok":true}
<else>
{"ok":false,"error":"Document not found."}
</ifrow>
</if>
<else>
<if value1="$[REQUEST_URI]" value2="/jobdocs/api/list" type="eq">
<header name="Content-Type" value="application/json">
<if value1="$[@_login_id]" value2="" type="eq">
{"ok":false,"error":"Not authorized."}
<else>
<if value1="$[job_id]" value2="" type="eq">
{"ok":false,"error":"job_id is required."}
<else>
<sql sessionid="">select d.id, d.name, d.submitted_date, d.mimetype, d.file_size,
u.name as submitted_by_name,
t.description as type_description,
s.description as subtype_description
from documents d
join users u on d.submitted_by=u.id
left join subtype s on d.subtype_id=s.id
left join type t on s.type_id=t.id
where d.job_id=$[job_id] and d.status='ACTIVE'
order by t.description, s.description, d.submitted_date desc</sql>$[sqlerror]
<set name="_doc_count" value="0">
{"ok":true,"documents":[<whilerow sessionid=""><if value1="$[_doc_count]" value2="0" type="ne">,</if>{"id":$[.id],"name":"$[.name]","submitted_date":"$[.submitted_date]","mimetype":"$[.mimetype]","file_size":$[.file_size],"submitted_by":"$[.submitted_by_name]","type":"$[.type_description]","subtype":"$[.subtype_description]"}<set name="_doc_count" value="1"></whilerow>]}
</if>
</if>
<else>
{"ok":false,"error":"Unknown route."}
</if>
</if>
</if>
</database>
+115
View File
@@ -0,0 +1,115 @@
<script>
function activate() {
document.getElementById('updatejobbutton').style.display='block';
}
function mandatory(obj) {
if(obj.value=='') {
obj.style.backgroundColor = '#fcc';
} else {
obj.style.backgroundColor = '#00000000';
}
}
</script>
<table style="width: 100%;">
<tr><th style="width: 30%;">Job Number:</th><td><input
<if value1="$[haserror]" value2="1" type="eq">
style="background-color: #fcc;"
</if>
type="text" name="jobnumber" value="$[jobnumber]" oninput="activate();"></td></tr>
<tr><th>Job Name:</th><td><input id="job_name" type="text" name="job_name" value="$[job_name]" oninput="activate(); mandatory(this);"></td></tr>
<script>
var job_name = document.getElementById('job_name');
mandatory(job_name);
</script>
<tr><th>Customer:</th><td><input list="customers" name="customer_name" id="customer_name" value="$[customer_name]" oninput="activate();">
<if value1="$[customer_id]" value2="" type="eq">
<input id="selected" type="hidden" name="customer_id" value="null">
<else>
<input id="selected" type="hidden" name="customer_id" value="$[customer_id]">
</if>
<datalist id="customers">
<sql>select * from customers order by name</sql>
<script>
var customer_name = document.getElementById('customer_name');
customer_name.addEventListener('input', (e) => {
var selected = document.getElementById('selected');
if(e.target.value.trim() == '') {
selected.value = 'null';
} else {
var option = document.querySelector('option[value="' + e.target.value.trim() + '"]');
if(option == null) {
selected.value = 0;
} else {
selected.value = option.id;
}
}
});
var customers = document.getElementById('customers');
<whilerow>
var option = document.createElement('option');
option.setAttribute("value","$[.name]");
option.id = $[.id];
customers.appendChild(option);
</whilerow>
</script>
</datalist>
</td></tr>
<tr><th>Contractor:</th><td><input list="contractors" name="contractor_name" id="contractor_name" value="$[contractor_name]" oninput="activate();">
<if value1="$[contractor_id]" value2="" type="eq">
<input id="selected2" type="hidden" name="contractor_id" value="null">
<else>
<input id="selected2" type="hidden" name="contractor_id" value="$[contractor_id]">
</if>
<sql>select *,trim(name) as tname from contractors order by name</sql>
<datalist id="contractors">
<script>
var contractor_name = document.getElementById('contractor_name');
contractor_name.addEventListener('input', (e) => {
var selected2 = document.getElementById('selected2');
if(e.target.value.trim() == '') {
selected2.value = 'null';
} else {
var option = contractors.querySelector('option[value="' + e.target.value.trim() + '"]');
if(option == null) {
selected2.value = 0;
} else {
selected2.value = option.id;
}
}
});
var contractors = document.getElementById('contractors');
<whilerow>
var option = document.createElement('option');
option.setAttribute("value", "$[tname]");
option.id = $[.id];
contractors.appendChild(option);
</whilerow>
</script>
</datalist>
</td></tr>
<tr><th>Contractor Job Id:</th><td><input type="text" name="contractor_job_id" value="$[contractor_job_id]" oninput="activate();"></td></tr>
<tr><th>Assessor Parcel Number:</th><td><input type="text" name="apn" value="$[apn]" oninput="activate();"></td></tr>
<tr><th>Insurance:</th><td><input type="text" name="insurance" value="$[insurance]" oninput="activate();"></td></tr>
<tr><th>Status:</th><td>
<select name="status_id" oninput="activate();">
<sql>select * from status where id=$[status_id]</sql>
<option value="$[.id]">$[.description]</option>
<sql>select e.to_status as to_status,
s.description as state_description,
e.description as description
from events e
join status s on s.id=e.to_status
where e.from_status=$[status_id]</sql>
<whilerow>
<option value="$[.to_status]">$[state_description] - $[.description]</option>
</whilerow>
</select>
</td></tr>
</table>
<div id="updatejobbutton" style="display: none;">
<abutton process="updatejobfolder">Update Job</abutton>
</div>
+104
View File
@@ -0,0 +1,104 @@
<script>
function setrows(include) {
var table = document.getElementById("list");
for (var i = 1; row = table.rows[i]; i++) {
if(include == "") {
row.style.visibility = "visible";
} else {
row.style.visibility = "collapse";
}
for (var j = 0; col = row.cells[j]; j++) {
if(col.innerHTML.toUpperCase().includes(include.toUpperCase())) {
row.style.visibility = "visible";
}
}
}
}
</script>
<retain name="selected_job_id">
<div>
<h2>JOBS</h2>
<div style="padding: 5px;">
<sql>
select *,
cu.name as customer,
co.name as contractor,
a.address1 as address,
c1.name as repname,
c2.name as supervisor,
c2.phone as supervisor_phone,
s.id as status_id
from jobs j
join status_users su on su.status_id=j.status_id and su.user_id=$[_login_id]
left outer join customers cu on j.customer_id=cu.id
left outer join contractors co on j.contractor_id=co.id
left outer join job_addresses ja on ja.job_id=j.id and ja.address_type=1
left outer join addresses a on ja.address_id=a.id
left outer join job_contacts jc1 on jc1.job_id=j.id and jc1.contact_type=3
left outer join contacts c1 on jc1.contact_id=c1.id
left outer join job_contacts jc2 on jc2.job_id=j.id and jc2.contact_type=1
left outer join contacts c2 on jc2.contact_id=c2.id
join status s on j.status_id=s.id
where (job_number is not null or job_name is not null)
order by s.sequence,job_name</sql>$[sqlerror]
<ifrow>
<div style="display: inline-block;">Jobs</div>
<div style="border-radius: 5px; display: inline-block; background: #345; color: #def; margin-left: 20px; padding: 5px;">
<img style="margin-top: 3px;" src="/assets/magglass.png" width="20px;" align="top">
<input style="font-size: 20px; color: #def; width: 90%;" type="text" size="40" name="search" value="" onkeyup="setrows(this.value); return true;">
</div>
<div>
<table id="list">
<tr>
<th style="text-align: center;">Job Number</th>
<th style="text-align: center;">Job Name</th>
<th style="text-align: center;">Contractor</th>
<th style="text-align: center;">Job Site Address</th>
<th style="text-align: center;">QI Rep</th>
<th style="text-align: center;">Supervisor</th>
<th style="text-align: center;">Supervisor Phone</th>
</tr>
<script>
function rowhover(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DDC';
td.style.cursor = 'pointer';
}
}
function rowout(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DEF';
td.style.cursor = 'default';
}
}
function goto(id) {
document.forms[0].PAGE.value = 'job';
document.forms[0].PROCESS.value = 'selectjob';
document.forms[0].selected_job_id.value = id;
document.forms[0].requestSubmit();
}
</script>
<set name="laststatusid" value="">
<whilerow>
<if value1="$[laststatusid]" value2="$[status_id]" type="ne">
<th colspan="7" style="text-align: left;">$[.description]</th>
<set name="laststatusid" value="$[.status_id]">
</if>
<tr style="visibility: table-row" onmouseenter="rowhover(this);" onmouseleave="rowout(this);" onclick="goto('$[.id]');">
<td>$[.job_number]</td>
<td>$[.job_name]</td>
<td>$[.contractor]</td>
<td>$[.address]</td>
<td>$[.repname]</td>
<td>$[.supervisor]</td>
<td>$[.supervisor_phone]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</div>
+102
View File
@@ -0,0 +1,102 @@
<page>
<title>Quality Iron</title>
<contents>
<script>
function setrows(include) {
var table = document.getElementById("list");
for (var i = 1; row = table.rows[i]; i++) {
if(include == "") {
row.style.visibility = "visible";
} else {
row.style.visibility = "collapse";
}
for (var j = 0; col = row.cells[j]; j++) {
if(col.innerHTML.toUpperCase().includes(include.toUpperCase())) {
row.style.visibility = "visible";
}
}
}
}
function rowhover(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DDC';
td.style.cursor = 'pointer';
}
}
function rowout(e) {
const tds = e.querySelectorAll('td');
for(td of tds) {
td.style.backgroundColor = '#DEF';
td.style.cursor = 'default';
}
}
function goto(id) {
document.forms[0].PAGE.value = 'job';
document.forms[0].PROCESS.value = 'selectjob';
document.forms[0].selected_job_id.value = id;
document.forms[0].requestSubmit();
}
</script>
<retain name="selected_job_id">
<div>
<h1>JOBS</h1>
<div style="padding: 5px;">
<sql>
select *,
cu.name as customer,
co.name as contractor,
a.address1 as address,
c1.name as repname,
c2.name as supervisor,
c2.phone as supervisor_phone
from jobs j
left outer join customers cu on j.customer_id=cu.id
left outer join contractors co on j.contractor_id=co.id
left outer join job_addresses ja on ja.job_id=j.id and ja.address_type=1
left outer join addresses a on ja.address_id=a.id
left outer join job_contacts jc1 on jc1.job_id=j.id and jc1.contact_type=3
left outer join contacts c1 on jc1.contact_id=c1.id
left outer join job_contacts jc2 on jc2.job_id=j.id and jc2.contact_type=1
left outer join contacts c2 on jc2.contact_id=c2.id
join status on j.status_id=status.id
where (job_number is not null or job_name is not null)
order by job_name</sql>$[sqlerror]
<ifrow>
<div style="display: inline-block;">Jobs</div>
<div style="border-radius: 5px; display: inline-block; background: #345; color: #def; margin-left: 20px; padding: 5px;">
<img style="margin-top: 3px;" src="/assets/magglass.png" width="20px;" align="top">
<input style="font-size: 20px; color: #def; width: 90%;" type="text" size="40" name="search" value="" onkeyup="setrows(this.value); return true;">
</div>
</div>
<div>
<table id="list">
<tr>
<th style="text-align: center;">Job Number</th>
<th style="text-align: center;">Job Name</th>
<th style="text-align: center;">Contractor</th>
<th style="text-align: center;">Job Site Address</th>
<th style="text-align: center;">QI Rep</th>
<th style="text-align: center;">Supervisor</th>
<th style="text-align: center;">Supervisor Phone</th>
<th style="text-align: center;">Status</th>
</tr>
<whilerow>
<tr style="visibility: table-row" onmouseenter="rowhover(this);" onmouseleave="rowout(this);" onclick="goto('$[.id]');">
<td>$[.job_number]</td>
<td>$[.job_name]</td>
<td>$[.contractor]</td>
<td>$[.address]</td>
<td>$[.repname]</td>
<td>$[.supervisor]</td>
<td>$[.supervisor_phone]</td>
<td>$[.description]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</contents>
</page>
+4
View File
@@ -0,0 +1,4 @@
<if value1="$[_login_id]" value2="" type="ne">
<div style="color: #234; font-size: 14px;">Welcome, $[_login_name]</div>
<linkbutton process="logout" class="button">Logout</linkbutton>
</if>
+14
View File
@@ -0,0 +1,14 @@
<sql>select * from users where name="$[username]" and secret="$[secret]"</sql>
<ifrow>
<set name="_login_id" value="$[.id]">
<set name="_login_name" value="$[.name]">
<set name="_login_email" value="$[.email]">
<if value1="$[_session_id]" value2="" type="eq">
<createsession>
</if>
<setenv name="_login_id">$[_login_id]</setenv>
<setenv name="_login_name">$[_login_name]</setenv>
<setenv name="_login_email">$[_login_email]</setenv>
<sql>update users set last_login=now() where id=$[_login_id]</sql>
<setpage name="home">
</ifrow>
+20
View File
@@ -0,0 +1,20 @@
<page>
<title>Quality Iron Login</title>
<contents>
<div style="width: 300px; border: 1pt solid #789; margin: 60px auto 0px auto; background-color: #abc;">
<div style="background-color: #123; color: #def; padding: 3px;">Login</div>
<img style="padding: 5px;" src="/assets/qi_logo.png">
<div style="margin: 10px 0px 0px 0px;">
<div style="display: inline-block; width: 100px; padding: 3px; text-align: right;"><span>User Name:&nbsp;</span></div>
<div style="display: inline-block; width: 190px;"><input type="text" name="username" style="width: 150px;"></div>
</div>
<div style="margin: 10px 0px 0px 0px;">
<div style="display: inline-block; width: 100px; padding: 3px; text-align: right;"><span>Password:&nbsp;</span></div>
<div style="display: inline-block; width: 190px;"><input type="password" name="secret" style="width: 150px;"></div>
</div>
<div style="margin: 10px 0px 10px 0px;">
<div style="display: inline-block; width: 290px; text-align: center;"><abutton process="login">Login</abutton></div>
</div>
</div>
</contents>
</page>
+3
View File
@@ -0,0 +1,3 @@
<process>
<include file="qualityiron-site/login.method">
</process>
+6
View File
@@ -0,0 +1,6 @@
<process>
<setenv name="_login_id"></setenv>
<setenv name="_login_email"></setenv>
<setenv name="_login_name"></setenv>
<setpage name="login">
</process>
@@ -0,0 +1,127 @@
#api GET /
#api GET /{page}
#api GET /{page}/{subpage}
#api POST /
#api POST /{page}
#api POST /{page}/{subpage}
<include file="SESSIONCTL.tag">
<set name="host" value="localhost">
<set name="database" value="qualityiron">
<set name="user" value="barant">
<set name="password" value="uversa1960">
<database name="$[database]" host="$[host]" user="$[user]" password="$[password]" sessionid="">
<if value1="$[PROCESS]" value2="" type="ne">
<tag name="process" scope="local"><eval><container></eval></tag>
<eval name="_procout"><include file="./qualityiron-site/$[DIR]/$[PROCESS].proc"></eval>
</if>
<checksession>
<if value1="$[PAGE]" value2="" type="eq">
<if value1="$[page]" value2="" type="eq">
<set name="PAGE" value="home">
<else>
<set name="PAGE" value="$[page]">
</if>
</if>
<if value1="$[DIR]" value2="" type="eq">
<set name="DIR" value="">
</if>
<if value1="$[SUBPAGE]" value2="" type="eq">
<if value1="$[subpage]" value2="" type="ne">
<set name="SUBPAGE" value="$[subpage]">
</if>
</if>
<tag name="page" keywords="class onload" scope="local">
<tag name="contents" scope="local"><eval name="_BODY"><container></eval></tag>
<eval name="_leftover"><container></eval>
$[_BODY]
</tag>
<set name="_needslogin" value="">
<if value1="$[PAGE]" value2="login" type="ne">
<if value1="$[_login_id]" value2="" type="eq">
<set name="_needslogin" value="1">
</if>
</if>
<if value1="$[_needslogin]" value2="1" type="eq">
<if value1="$[_fragment]" value2="" type="eq">
<html><head><meta http-equiv="refresh" content="0; url=https://$[HTTP_HOST]/login?start=$[PAGE]"></head></html>
<else>
<div data-spa-redirect="/login?start=$[PAGE]"></div>
</if>
<else>
<if value1="$[_fragment]" value2="" type="eq">
<!DOCTYPE html>
<html lang="en">
<head>
<title>Quality Iron Works</title>
<link rel="stylesheet" href="/assets/main.css?v=20260924b">
</head>
<body>
<form id="mainform" method="post" action="/$[PAGE]<if value1="$[SUBPAGE]" value2="" type="ne">/$[SUBPAGE]</if>" enctype="multipart/form-data">
<input type="hidden" name="_LASTPAGE" value="$[PAGE]">
<input type="hidden" name="PROCESS" value="">
<input type="hidden" name="EXITPROCESS" value="">
<input type="hidden" name="DIR" value="">
<input type="hidden" name="_CTLDIR" value="">
<input type="hidden" name="PAGE" value="$[PAGE]">
<input type="hidden" name="SUBPAGE" value="$[SUBPAGE]">
<input type="hidden" name="_TIMESTAMP" value="">
<div class="pageclass">
<div class="heading">
<div style="display: inline-block;">
<a href="https://qualityiron.vegas"><img style="height: 50px; margin: 8px;" src="/assets/qi_logo.png"></a>
</div>
<div id="loginmenu" style="float: right; text-align: right; margin-right: 10px; margin-top: 15px;"><include file="qualityiron-site/login.bar"></div>
</div>
<div class="menubar" id="menubar">
<include file="qualityiron-site/functions.menu">
</div>
<div style="display: flex; flex: 1; width: 100%; min-height: 0;">
<div class="panel" id="content" style="flex: 1; min-width: 0; padding: 10px;">
<try>
<eval><include file="./qualityiron-site/$[DIR]/$[PAGE].page"></eval>
<catch>
<p>Page not found.</p>
</try>
</div>
</div>
<div class="footer" style="clear: both;">&copy; Quality Iron Works</div>
</div>
</form>
<div id="filemgr-panel" class="filemgr-collapsed">
<div id="filemgr-toggle" title="File Transfers">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V6M5 12l7-7 7 7"/><path d="M5 21h14"/></svg>
<span id="filemgr-badge"></span>
</div>
<div id="filemgr-body">
<div id="filemgr-header">
<span>Transfers</span>
<span id="filemgr-clear" title="Clear completed">Clear</span>
</div>
<div id="filemgr-list"><div id="filemgr-empty">No transfers yet.</div></div>
</div>
</div>
<script src="/assets/spa.js?v=20260922a"></script>
<script src="/assets/jobdocs.js?v=20260924a"></script>
</body>
</html>
<else>
<div data-spa-page="$[PAGE]" data-spa-subpage="$[SUBPAGE]" style="display:none"></div>
<div id="_spa_menubar" style="display:none"><include file="qualityiron-site/functions.menu"></div>
<div id="_spa_loginmenu" style="display:none"><include file="qualityiron-site/login.bar"></div>
<try>
<eval><include file="./qualityiron-site/$[DIR]/$[PAGE].page"></eval>
<catch>
<p>Page not found.</p>
</try>
</if>
</if>
</database>
+61
View File
@@ -0,0 +1,61 @@
<page>
<title>Quality Iron - My Profile</title>
<contents>
<div>
<h1>MY PROFILE</h1>
<sql>select * from users where id=$[@_login_id]</sql>$[sqlerror]
<ifrow>
<div>
<table>
<tr>
<th></th>
<th>Name</th>
<th>E-Mail</th>
<th>Phone</th>
<th>Last Login</th>
</tr>
<tr>
<td><linkbutton page="edituser" process="selectuser" name="selected_user_id" value="$[.id]">Edit</linkbutton></td>
<td>$[.name]</td>
<td>$[.email]</td>
<td>$[.phone]</td>
<td>$[.last_login]</td>
</tr>
</table>
</div>
</ifrow>
</div>
<div>
<h2>STATUS VALUES</h2>
<sql> select s.id as status_id,
s.description as description,
s.comment as comment,
su.id as status_user_id
from status s
left outer join status_users su on s.id=su.status_id and su.user_id=$[@_login_id]
where (su.user_id=$[@_login_id] or su.user_id is null)
order by sequence</sql>$[sqlerror]
<div>
<table>
<tr>
<th></th>
<th>Description</th>
<th>Comment</th>
</tr>
<whilerow>
<tr>
<td><input type="checkbox" name="select$[.status_id]" value="on"
<if value1="$[.status_user_id]" value2="" type="ne">checked</if>
></td>
<td>$[.description]</td>
<td>$[.comment]</td>
</tr>
</whilerow>
</table>
</div>
<abutton process="updatestatususer">Update</abutton>
</div>
</contents>
</page>
+36
View File
@@ -0,0 +1,36 @@
<page>
<title>Quality Iron - Roles</title>
<contents>
<retain name="selected_role_id">
<div>
<h1>USER ROLES</h1>
<sql>select r.*,
(select count(*) from user_roles ur where ur.role_id=r.id) as count
from roles r
order by description</sql>$[sqlerror]
<table id="role_table">
<tr>
<th></th>
<th style="text-align: left;">Description</th>
<th style="text-align: left;">Used</th>
<th></th>
</tr>
<whilerow>
<tr>
<td>
<if value1="$[.count]" value2="0" type="eq">
<linkbutton process="deleterole" name="selected_role_id" value="$[.id]"><img width="18" style="cursor: pointer;" src="/assets/delete.png"></linkbutton>
</if>
</td>
<td><input type="text" name="description$[.id]" size="20" value="$[.description]"></td>
<td>$[.count]</td>
<td><linkbutton process="updaterole" name="selected_role_id" value="$[.id]">Save</linkbutton></td>
</tr>
</whilerow>
</table>
<h2>Add Role</h2>
<input type="text" name="new_role_description" size="20" value="">
<abutton process="createrole">Add</abutton>
</div>
</contents>
</page>
@@ -0,0 +1,3 @@
<process>
<setenv name="_selected_contractor_id">$[selected_contractor_id]</setenv>
</process>
@@ -0,0 +1,3 @@
<process>
<setenv name="_selected_customer_id">$[selected_customer_id]</setenv>
</process>
+3
View File
@@ -0,0 +1,3 @@
<process>
<setenv name="_selected_job_id">$[selected_job_id]</setenv>
</process>
@@ -0,0 +1,3 @@
<process>
<setenv name="_selected_user_id">$[selected_user_id]</setenv>
</process>
+9
View File
@@ -0,0 +1,9 @@
<process>
<set name="x_notation" value="$[notation]">
<sql>insert into job_reviews
set job_id=$[@_selected_job_id],
review_date='$[review_date]',
notation='$[x_notation]',
owner=$[@_login_id]
</sql>$[sqlerror]
</process>
@@ -0,0 +1,18 @@
<process>
<set name="x_name" value="$[name]">
<set name="x_address1" value="$[address1]">
<set name="x_address2" value="$[address2]">
<sql>
update contractors
set name='$[x_name]',
address1='$[x_address1]',
address2='$[x_address2]',
city='$[city]',
state='$[state]',
zip_code='$[zip_code]',
contact='$[contact]',
contact_phone='$[contact_phone]',
contact_email='$[contact_email]'
where id=$[@_selected_contractor_id]
</sql>$[sqlerror]
</process>
@@ -0,0 +1,8 @@
<process>
<set name="x_name" value="$[name]">
<sql>
update customers
set name='$[x_name]'
where id=$[@_selected_customer_id]
</sql>$[sqlerror]
</process>
@@ -0,0 +1,18 @@
<process>
<database host="$[host]" name="$[database]" user="$[user]" password="$[password]" sessionid="2">
<sql>select *,
dt.id as date_type_id
from date_types dt
left outer join job_dates jd on jd.type=dt.id and jd.job_id=$[@_selected_job_id]
</sql>
<whilerow>
<sql sessionid="2">
<if value1="$[date$[.date_type_id]]" value2="" type="eq">
delete from job_dates where job_id=$[@_selected_job_id] and type=$[.date_type_id]
<else>
replace into job_dates set job_id=$[@_selected_job_id],type=$[.date_type_id],date='$[date$[.date_type_id]]',owner=$[@_login_id]
</if>
</sql>$[sqlerror]
</whilerow>
</database>
</process>
@@ -0,0 +1,173 @@
<process>
<sql>
select * from jobs where id=$[@_selected_job_id]
</sql>
<set name="o_job_number" value="$[.job_number]">
<set name="o_job_name" value="$[.job_name]">
<set name="o_status_id" value="$[.status_id]">
<set name="o_customer_id" value="$[.customer_id]">
<set name="o_contractor_id" value="$[.contractor_id]">
<set name="o_contractor_job_id" value="$[.contractor_job_id]">
<set name="o_apn" value="$[.apn]">
<set name="o_insurance" value="$[.insurance]">
<set name="x_jobnumber" value="$[jobnumber]">
<if value1="$[x_jobnumber]" value2="" type="ne">
<sql>select * from jobs where job_number='$[x_jobnumber]'</sql>
<ifrow>
<if value1="$[.id]" value2="$[@_selected_job_id]" type="ne">
<set name="message" value="Job Number already exists.">
<set name="haserror" value="1">
</if>
</ifrow>
</if>
<set name="x_job_name" value="$[job_name]">
<if value1="$[x_job_name]" value2="" type="eq">
<if value1="$[message]" value2="" type="ne">
<set name="message" value="$[message]<br>">
</if>
<set name="message" value="$[message]Job Name cannot be blank.">
</if>
<if value1="$[message]" value2="" type="eq">
<set name="x_contractor_job_id" value="$[contractor_job_id]">
<set name="x_customer_name" value="$[customer_name]">
<if value1="$[customer_id]" value2="0" type="eq">
<sql>insert into customers set name=trim("$[x_customer_name]"), created=now(),owner=$[@_login_id]</sql>$[sqlerror]
<sql>select last_insert_id() as customer_id</sql>$[sqlerror]
<set name="customer_id" value="$[.customer_id]">
</if>
<set name="contractor_id" value="$[contractor_id]">
<set name="x_contractor_name" value="$[contractor_name]">
<if value1="$[contractor_id]" value2="0" type="eq">
<sql>insert into contractors set name=trim("$[x_contractor_name]"), created=now(),owner=$[@_login_id]</sql>$[sqlerror]
<sql>select last_insert_id() as contractor_id</sql>$[sqlerror]
<set name="contractor_id" value="$[.contractor_id]">
</if>
<sql>
update jobs
set job_number=<if value1="$[x_jobnumber]" value2="" type="eq">null<else>'$[x_jobnumber]'</if>,
job_name=trim('$[x_job_name]'),
customer_id=$[customer_id],
created=now(),
status_id=$[status_id],
contractor_id=$[contractor_id],
contractor_job_id='$[x_contractor_job_id]',
apn='$[apn]',
insurance='$[insurance]'
where id=$[@_selected_job_id]
</sql>$[sqlerror]
<if value1="$[o_job_number]" value2="$[jobnumber]" type="ne">
<set name="ox_job_number" value="$[o_job_number]">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0002',
text='Job Number updated from "$[ox_job_number]" to "$[x_jobnumber]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_job_name]" value2="$[job_name]" type="ne">
<set name="ox_job_name" value="$[o_job_name]">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0003',
text='Job Name updated from "$[ox_job_name]" to "$[x_job_name]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_customer_id]" value2="" type="eq">
<set name="o_customer_id" value="null">
</if>
<if value1="$[o_customer_id]" value2="$[customer_id]" type="ne">
<sql>select * from customers where id=$[customer_id]</sql>
<ifrow>
<set name="x_customer_name" value="$[.name]">
<else>
<set name="x_customer_name" value="">
</ifrow>
<if value1="$[o_customer_id]" value2="null" type="ne">
<sql>select * from customers where id=$[o_customer_id]</sql>
<ifrow>
<set name="ox_customer_name" value="$[.name]">
<else>
<set name="ox_customer_name" value="">
</ifrow>
<else>
<set name="ox_customer_name" value="">
</if>
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0004',
text='Job Customer updated from "$[ox_customer_name]" to "$[x_customer_name]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_contractor_id]" value2="$[contractor_id]" type="ne">
<sql>select * from contractors where id=$[contractor_id]</sql>
<set name="x_contractor_name" value="$[.name]">
<sql>select * from contractors where id=$[o_contractor_id]</sql>
<set name="ox_contractor_name" value="$[.name]">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0005',
text='Job Contractor updated from "$[ox_contractor_name]" to "$[x_contractor_name]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_contractor_job_id]" value2="$[contractor_job_id]" type="ne">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0006',
text='Job Contractor Job Id updated from "$[o_contractor_job_id]" to "$[x_contractor_job_id]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_apn]" value2="$[apn]" type="ne">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0009',
text='Assessor Parcel Number updated from "$[o_apn]" to "$[apn]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_insurance]" value2="$[insurance]" type="ne">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0007',
text='Job Insurance updated from "$[o_insurance]" to "$[insurance]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
<if value1="$[o_status_id]" value2="$[status_id]" type="ne">
<sql>select * from status where id=$[status_id]</sql>
<set name="x_status" value="$[.description]">
<sql>select * from status where id=$[o_status_id]</sql>
<set name="o_status" value="$[.description]">
<sql>insert into job_activity_log
set created=now(),
job_id=$[@_selected_job_id],
user_id=$[@_login_id],
message_id='JOB0008',
text='Job Status updated from "$[o_status]" to "$[x_status]".',
url='/job?id=$[@_selected_job_id]'
</sql>$[sqlerror]
</if>
</if>
</process>
@@ -0,0 +1,4 @@
<process>
<set name="x_description" value="$[description$[selected_role_id]]">
<sql>update roles set description='$[x_description]' where id=$[selected_role_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,6 @@
<process>
<set name="x_description" value="$[description$[selected_status_id]]">
<set name="x_comment" value="$[comment$[selected_status_id]]">
<set name="x_sequence" value="$[sequence$[selected_status_id]]">
<sql>update status set description='$[x_description]', comment='$[x_comment]', sequence=$[x_sequence] where id=$[selected_status_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,11 @@
<process>
<database host="$[host]" name="$[database]" user="$[user]" password="$[password]" sessionid="2">
<sql sessionid="2">delete from status_users where user_id=$[@_login_id]</sql>$[sqlerror]
<sql>select * from status</sql>$[sqlerror]
<whilerow>
<if value1="$[select$[.id]]" value2="on" type="eq">
<sql sessionid="2">insert into status_users set status_id=$[.id],user_id=$[@_login_id]</sql>$[sqlerror]
</if>
</whilerow>
</database>
</process>
@@ -0,0 +1,4 @@
<process>
<set name="x_description" value="$[subtypedescription$[selected_subtype_id]]">
<sql>update subtype set description='$[x_description]' where id=$[selected_subtype_id]</sql>$[sqlerror]
</process>
@@ -0,0 +1,4 @@
<process>
<set name="x_description" value="$[typedescription$[selected_type_id]]">
<sql>update type set description='$[x_description]' where id=$[selected_type_id]</sql>$[sqlerror]
</process>
+13
View File
@@ -0,0 +1,13 @@
<process>
<set name="x_username" value="$[username]">
<set name="x_email" value="$[email]">
<sql>
update users
set name='$[x_username]',
secret='$[secret]',
email='$[x_email]',
phone='$[phone]',
allow_user_maint=if('$[allow_user_maint]'='Y','Y','N')
where id=$[@_selected_user_id]
</sql>$[sqlerror]
</process>
+14
View File
@@ -0,0 +1,14 @@
<tr><td style="width: 250px;">User Name:</td>
<td><input type="text" name="username" size="20" value="$[username]"></td></tr>
<tr><td>Password:</td>
<td><input type="password" name="secret" size="20" value="$[secret]"></td></tr>
<tr><td>Verify Password:</td>
<td><input type="password" name="verify" size="20" value="$[verify]"></td></tr>
<tr><td>E-Mail:</td>
<td><input type="text" name="email" size="75" value="$[email]"></td></tr>
<tr><td>Phone:</td>
<td><input type="text" name="phone" size="75" value="$[phone]"></td></tr>
<tr><td>Grant Admin rights?:</td>
<td><input type="checkbox" name="allow_user_maint" value="Y"
<if value1="$[allow_user_maint]" value2="Y" type="eq">checked</if>
></td></tr>
+36
View File
@@ -0,0 +1,36 @@
<page>
<title>Quality Iron - Users</title>
<contents>
<retain name="selected_user_id">
<div>
<h1>USERS</h1>
<linkbutton page="createuser">Create User</linkbutton>
<sql>select *,
date_format(convert_tz(last_login,'UTC','America/Los_Angeles'), "%W, %M %D, %Y %l:%i%p") as last_login_date
from users order by name</sql>$[sqlerror]
<ifrow>
<div>Users</div>
<div>
<table>
<tr>
<th></th>
<th>Name</th>
<th>E-Mail</th>
<th>Phone</th>
<th>Last Login</th>
</tr>
<whilerow>
<tr>
<td><linkbutton page="edituser" process="selectuser" name="selected_user_id" value="$[.id]">Edit</linkbutton></td>
<td>$[.name]</td>
<td>$[.email]</td>
<td>$[.phone]</td>
<td>$[.last_login_date]</td>
</tr>
</whilerow>
</table>
</div>
</ifrow>
</div>
</contents>
</page>