att
This commit is contained in:
parent
0754466359
commit
b32415212f
2168
.metadata/.log
2168
.metadata/.log
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.debug.ui.PREF_LAUNCH_PERSPECTIVES=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?>\r\n<launchPerspectives/>\r\n
|
||||
preferredTargets=default\:default|default,org.eclipse.wst.jsdt.chromium.debug.ui.toggleTargetId\:default|
|
||||
preferredTargets=default\:default|default,org.eclipse.wst.jsdt.chromium.debug.ui.toggleTargetId\:default|org.eclipse.wst.jsdt.chromium.debug.ui.toggleTargetId\:org.eclipse.wst.jsdt.chromium.debug.ui.toggleTargetId|
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
browsers=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<web-browsers current\="0">\r\n<system/>\r\n<external location\="C\:\\Program Files\\Internet Explorer\\iexplore.exe" name\="Internet Explorer"/>\r\n<external location\="C\:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" name\="Chrome"/>\r\n</web-browsers>
|
||||
eclipse.preferences.version=1
|
||||
internalWebBrowserHistory=file\:///C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/layout/TIginseng_layoutblocado/src/main/webapp/resources/images/icon.png|*|file\:/C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/layout/TIginseng_layoutblocado/src/main/webapp/resources/images/icon.png|*|file\:///C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/widget/widget_code_compras/src/main/webapp/resources/images/icon.png|*|file\:/C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/widget/widget_code_compras/src/main/webapp/resources/images/icon.png|*|
|
||||
internalWebBrowserHistory=file\:///C\:/Users/andrey.cunha/eclipse-workspace.new/Auditoria_checklist/wcm/widget/helloWidget/src/main/webapp/resources/images/dev.png|*|file\:/C\:/Users/andrey.cunha/eclipse-workspace.new/Auditoria_checklist/wcm/widget/helloWidget/src/main/webapp/resources/images/dev.png|*|file\:///C\:/Users/andrey.cunha/eclipse-workspace.new/Auditoria_checklist/wcm/widget/helloWidget/src/main/webapp/resources/images/icon.png|*|file\:/C\:/Users/andrey.cunha/eclipse-workspace.new/Auditoria_checklist/wcm/widget/helloWidget/src/main/webapp/resources/images/icon.png|*|file\:///C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/layout/TIginseng_layoutblocado/src/main/webapp/resources/images/icon.png|*|file\:/C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/layout/TIginseng_layoutblocado/src/main/webapp/resources/images/icon.png|*|file\:///C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/widget/widget_code_compras/src/main/webapp/resources/images/icon.png|*|file\:/C\:/Users/andrey.cunha/eclipse-workspace.new/Ginseng_chamados/wcm/widget/widget_code_compras/src/main/webapp/resources/images/icon.png|*|
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -183,3 +183,5 @@
|
||||
2026-02-23 10:29:20,949 [Worker-4: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is out-of-date. Trying to update.
|
||||
2026-02-24 10:35:56,560 [Worker-3: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is out-of-date. Trying to update.
|
||||
2026-02-27 16:07:17,391 [Worker-3: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is out-of-date. Trying to update.
|
||||
2026-03-05 14:13:17,734 [Worker-6: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is out-of-date. Trying to update.
|
||||
2026-03-06 09:35:04,306 [Worker-6: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
|
||||
|
||||
@ -1,22 +1,12 @@
|
||||
INDEX VERSION 1.4+C:\Users\andrey.cunha\eclipse-workspace.new\.metadata\.plugins\org.eclipse.wst.jsdt.core\indexes
|
||||
3963123655.index
|
||||
3049976914.index
|
||||
1889139231.index
|
||||
2056597484.index
|
||||
1252593962.index
|
||||
160423874.index
|
||||
3477032517.index
|
||||
3528551409.index
|
||||
17091598.index
|
||||
4202715187.index
|
||||
3974601650.index
|
||||
1053469344.index
|
||||
3371662347.index
|
||||
3537614094.index
|
||||
1338284093.index
|
||||
1604404410.index
|
||||
2070855566.index
|
||||
1999126708.index
|
||||
707046764.index
|
||||
223663271.index
|
||||
1180771715.index
|
||||
2887418869.index
|
||||
3963123655.index
|
||||
7156200.index
|
||||
2938933076.index
|
||||
3537614094.index
|
||||
1300356610.index
|
||||
3826028853.index
|
||||
3670622443.index
|
||||
|
||||
Binary file not shown.
18
Auditoria/.project
Normal file
18
Auditoria/.project
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Auditoria</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
<nature>com.totvs.tds.ecm.designer.nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
118
Auditoria/datasets/ds_lojas_api.js
Normal file
118
Auditoria/datasets/ds_lojas_api.js
Normal file
@ -0,0 +1,118 @@
|
||||
function createDataset(fields, constraints, sortFields) {
|
||||
var dataset = DatasetBuilder.newDataset();
|
||||
dataset.addColumn("PDV");
|
||||
dataset.addColumn("LOJA");
|
||||
dataset.addColumn("RESPONSAVEL_LOJA");
|
||||
dataset.addColumn("REGIONAL");
|
||||
dataset.addColumn("UF");
|
||||
dataset.addColumn("CIDADE");
|
||||
dataset.addColumn("STATUS");
|
||||
dataset.addColumn("CANAL");
|
||||
dataset.addColumn("ID");
|
||||
dataset.addColumn("LOGIN_LOJA");
|
||||
dataset.addColumn("COLLEAGUE_ID");
|
||||
|
||||
try {
|
||||
var clientService = fluigAPI.getAuthorizeClientService();
|
||||
var data = {
|
||||
companyId: String(getValue("WKCompany") || "1"),
|
||||
serviceCode: "GINSENG API",
|
||||
endpoint: "/base_pdvs",
|
||||
method: "get",
|
||||
timeoutService: "60000",
|
||||
params: {}
|
||||
};
|
||||
|
||||
var vo = clientService.invoke(JSON.stringify(data));
|
||||
var response = String(vo.getResult() || "");
|
||||
var obj = JSON.parse(response);
|
||||
var list = (obj && obj.data && obj.data.length) ? obj.data : [];
|
||||
|
||||
if (!list.length) {
|
||||
dataset.addRow(["", "Sem lojas retornadas", "", "", "", "", "", "", "", "", ""]);
|
||||
return dataset;
|
||||
}
|
||||
|
||||
var filter = getSearchFilter(constraints);
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var item = list[i] || {};
|
||||
var pdv = clean(item.PDV);
|
||||
var loja = clean(item["PDV DESC"] || item.DESCRICAO);
|
||||
var responsavel = clean(item.GESTAO);
|
||||
var regional = clean(item.SUPERVISOR || item["REGIAO 2"] || item.REGIAO);
|
||||
var uf = clean(item.UF || item["UF 2"]);
|
||||
var cidade = clean(item.CIDADE);
|
||||
var status = clean(item.STATUS);
|
||||
var canal = clean(item.CANAL);
|
||||
var id = clean(item.id);
|
||||
var loginLoja = pdv ? (pdv + ".ginseng") : "";
|
||||
var colleagueId = resolveColleagueId(loginLoja);
|
||||
|
||||
if (!matchesFilter(filter, [pdv, loja, responsavel, regional, uf, cidade, status, canal, loginLoja, colleagueId])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dataset.addRow([
|
||||
pdv,
|
||||
loja,
|
||||
responsavel,
|
||||
regional,
|
||||
uf,
|
||||
cidade,
|
||||
status,
|
||||
canal,
|
||||
id,
|
||||
loginLoja,
|
||||
colleagueId
|
||||
]);
|
||||
}
|
||||
} catch (e) {
|
||||
dataset = DatasetBuilder.newDataset();
|
||||
dataset.addColumn("ERRO");
|
||||
dataset.addRow([String(e)]);
|
||||
}
|
||||
|
||||
return dataset;
|
||||
}
|
||||
|
||||
function resolveColleagueId(login) {
|
||||
try {
|
||||
var c1 = DatasetFactory.createConstraint("login", login, login, ConstraintType.MUST);
|
||||
var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
var ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
|
||||
if (ds && ds.rowsCount > 0) {
|
||||
return clean(ds.getValue(0, "colleaguePK.colleagueId"));
|
||||
}
|
||||
} catch (e) {}
|
||||
return "";
|
||||
}
|
||||
|
||||
function getSearchFilter(constraints) {
|
||||
if (!constraints || !constraints.length) return "";
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
var c = constraints[i];
|
||||
var field = String(c.fieldName || "").toUpperCase();
|
||||
if (field === "SEARCH" || field === "LOJA" || field === "PDV") {
|
||||
return normalizeSearch(c.initialValue);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function matchesFilter(filter, values) {
|
||||
if (!filter) return true;
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (normalizeSearch(values[i]).indexOf(filter) > -1) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalizeSearch(text) {
|
||||
var t = clean(text).toUpperCase();
|
||||
t = t.replace(/[%*_]/g, "");
|
||||
return t;
|
||||
}
|
||||
|
||||
function clean(value) {
|
||||
return String(value || "").trim();
|
||||
}
|
||||
BIN
Auditoria/forms/auditoria_prototipo/.metadata
Normal file
BIN
Auditoria/forms/auditoria_prototipo/.metadata
Normal file
Binary file not shown.
585
Auditoria/forms/auditoria_prototipo/assets/css/css/checklist.css
Normal file
585
Auditoria/forms/auditoria_prototipo/assets/css/css/checklist.css
Normal file
@ -0,0 +1,585 @@
|
||||
body { background: #ffffff; }
|
||||
.audit-shell {
|
||||
background: #f4f8fd;
|
||||
border: 1px solid #dbe4ee;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 14px rgba(15, 23, 42, 0.06);
|
||||
padding: 10px 10px 14px 10px;
|
||||
margin: 14px auto 0 auto;
|
||||
max-width: 1140px;
|
||||
}
|
||||
.audit-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 14px;
|
||||
background: #ffffff;
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
h1.audit-main-title {
|
||||
margin: 2px 0 10px 0;
|
||||
font-size: 18px !important;
|
||||
line-height: 1.2;
|
||||
font-weight: 700 !important;
|
||||
color: #ffffff !important;
|
||||
background: #0b556b;
|
||||
border-radius: 10px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.section-title {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
}
|
||||
.audit-status {
|
||||
display: none;
|
||||
}
|
||||
.progress-section {
|
||||
padding: 5px 10px 5px 10px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.progress-section .section-title {
|
||||
font-size: 16px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.audit-context-card .section-title {
|
||||
font-size: 17px;
|
||||
}
|
||||
.progress-inline {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
.progress-track {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
border-radius: 999px;
|
||||
background: #e6ebf2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.progress-fill {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #3ea9c8 0%, #3ea9c8 100%);
|
||||
transition: width .18s ease-in-out;
|
||||
}
|
||||
.progress-percent {
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
color: #0f172a;
|
||||
font-weight: 700;
|
||||
min-width: 42px;
|
||||
text-align: right;
|
||||
}
|
||||
.progress-meta {
|
||||
margin-top: 3px;
|
||||
font-size: 9px;
|
||||
color: #52637b;
|
||||
font-weight: 600;
|
||||
}
|
||||
.instruction-section {
|
||||
display: block;
|
||||
background: #ffffff;
|
||||
}
|
||||
.intro-data-section {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(90deg, #f4f8fd 0%, #edf3fa 100%);
|
||||
}
|
||||
.intro-data-section .instruction-section {
|
||||
padding: 12px;
|
||||
border-radius: 14px 14px 0 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
.intro-divider {
|
||||
height: 1px;
|
||||
background: #dfe7f0;
|
||||
}
|
||||
.instruction-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.instruction-icon {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 999px;
|
||||
background: #3ea9c8;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
.instruction-title {
|
||||
font-size: 16px;
|
||||
color: #1f2f46;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.instruction-steps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(160px, 1fr));
|
||||
gap: 6px 16px;
|
||||
font-size: 10px;
|
||||
color: #334155;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.instruction-steps span {
|
||||
display: inline-block;
|
||||
border: 1px solid #b9d4ea;
|
||||
background: #f4f9ff;
|
||||
color: #0f3f66;
|
||||
border-radius: 999px;
|
||||
padding: 4px 9px;
|
||||
width: fit-content;
|
||||
}
|
||||
.status-pill {
|
||||
background: #eef5fb;
|
||||
border: 1px solid #d9e8f6;
|
||||
color: #0b556b;
|
||||
border-radius: 999px;
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.audit-context-card {
|
||||
background: #ffffff;
|
||||
padding: 12px;
|
||||
border-radius: 0 0 14px 14px;
|
||||
}
|
||||
.audit-context-row > div {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.audit-label {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.3px;
|
||||
color: #16486a;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.label-icon { opacity: 0.8; margin-right: 4px; }
|
||||
.audit-input {
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
border-color: #c9d7e7;
|
||||
border-radius: 7px;
|
||||
padding: 5px 9px;
|
||||
}
|
||||
.audit-input:focus {
|
||||
border-color: #74a5d3;
|
||||
box-shadow: 0 0 0 2px rgba(34, 93, 143, 0.12);
|
||||
}
|
||||
.audit-card { margin-top: 12px; }
|
||||
.audit-score { font-size: 22px; font-weight: 700; }
|
||||
.audit-score small { font-size: 12px; font-weight: 400; color: #7f8c8d; display: block; }
|
||||
#pilaresContainer {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(220px, 1fr));
|
||||
gap: 14px;
|
||||
background: #f4f8fd;
|
||||
border: 0;
|
||||
border-radius: 10px;
|
||||
padding: 8px 12px 10px 12px;
|
||||
}
|
||||
h2.section-title.pilares-title {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 17px !important;
|
||||
}
|
||||
.audit-send-wrap {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
padding: 10px 12px 2px 12px;
|
||||
border-top: 1px solid #dbe5f0;
|
||||
}
|
||||
.audit-send-btn {
|
||||
min-width: 120px;
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
background: #0b556b;
|
||||
border-color: #0b556b;
|
||||
}
|
||||
.audit-send-btn:hover,
|
||||
.audit-send-btn:focus {
|
||||
background: #0a4b5f;
|
||||
border-color: #0a4b5f;
|
||||
}
|
||||
.pilar-panel {
|
||||
border: 1px solid #d6e1ee;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
padding: 8px;
|
||||
min-height: 108px;
|
||||
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
|
||||
transition: box-shadow .18s ease, transform .18s ease;
|
||||
}
|
||||
.pilar-panel:hover {
|
||||
box-shadow: 0 10px 20px rgba(15, 23, 42, 0.12);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.pilar-panel.is-open {
|
||||
grid-column: 1 / -1;
|
||||
box-shadow: 0 12px 24px rgba(15, 23, 42, 0.14);
|
||||
}
|
||||
.pilar-summary-card {
|
||||
grid-column: span 3;
|
||||
border: 1px solid #d6e1ee;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
padding: 10px 12px;
|
||||
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
.summary-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.summary-item {
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
color: #000000;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.summary-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.summary-name {
|
||||
color: #000000;
|
||||
font-weight: 700;
|
||||
}
|
||||
.pilar-head {
|
||||
background: #ffffff;
|
||||
border: 0;
|
||||
padding: 6px;
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
transition: background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
|
||||
}
|
||||
.pilar-head:hover {
|
||||
background: #f8fbff;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
.pilar-head.is-open {
|
||||
background: #f4f8fd;
|
||||
box-shadow: none;
|
||||
}
|
||||
.pilar-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.pilar-state-dot {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 999px;
|
||||
background: #94a3b8;
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
.pilar-state-dot.state-pending { background: #dc2626; border-color: rgba(220, 38, 38, 0.4); }
|
||||
.pilar-state-dot.state-progress { background: #d18a2f; border-color: rgba(209, 138, 47, 0.35); }
|
||||
.pilar-state-dot.state-done { background: #2f9d78; border-color: rgba(47, 157, 120, 0.35); }
|
||||
.pilar-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
.pilar-photo-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #243549;
|
||||
}
|
||||
.pilar-photo-count {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
}
|
||||
.pilar-missing {
|
||||
font-size: 10px;
|
||||
color: #000000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.pilar-mini-track {
|
||||
height: 5px;
|
||||
border-radius: 999px;
|
||||
background: #e4eaf1;
|
||||
overflow: hidden;
|
||||
}
|
||||
.pilar-mini-fill {
|
||||
display: block;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: #5d8fbe;
|
||||
transition: width .18s ease;
|
||||
}
|
||||
.pilar-foot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.pilar-count {
|
||||
font-size: 10px;
|
||||
color: #000000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.pilar-open-cta {
|
||||
font-size: 10px;
|
||||
color: #000000;
|
||||
font-weight: 700;
|
||||
}
|
||||
.pilar-body { padding: 8px 0 0 0; }
|
||||
.audit-row {
|
||||
border: 1px solid #d4e0ee;
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
margin-bottom: 8px;
|
||||
background: #f9fcff;
|
||||
}
|
||||
.audit-row-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.audit-row-top {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.3fr;
|
||||
gap: 10px;
|
||||
align-items: start;
|
||||
}
|
||||
.audit-row[data-max-fotos="1"] .audit-row-top,
|
||||
.audit-row[data-max-fotos="2"] .audit-row-top {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.audit-info {
|
||||
min-width: 0;
|
||||
}
|
||||
.indicador-cell { font-weight: 700; color: #143653; font-size: 15px; line-height: 1.25; }
|
||||
.indicador-help {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
color: #5c6f82;
|
||||
line-height: 1.35;
|
||||
background: #f7fbff;
|
||||
border: 1px solid #dce8f5;
|
||||
border-radius: 8px;
|
||||
padding: 7px 9px;
|
||||
}
|
||||
.indicador-help ul {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
}
|
||||
.indicador-help li {
|
||||
margin: 2px 0;
|
||||
}
|
||||
.indicador-help .indicador-group {
|
||||
list-style: none;
|
||||
margin-top: 6px;
|
||||
margin-left: -18px;
|
||||
font-weight: 700;
|
||||
color: #36597b;
|
||||
}
|
||||
.meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(100px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.meta-box {
|
||||
border: 1px solid #d7e2ef;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
padding: 8px 10px;
|
||||
min-height: 62px;
|
||||
}
|
||||
.meta-label { font-size: 11px; color: #64748b; text-transform: uppercase; }
|
||||
.meta-value { font-size: 20px; color: #1f2937; margin-top: 4px; font-weight: 600; }
|
||||
.meta-value .form-control {
|
||||
font-size: 14px;
|
||||
height: 34px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
.anexo-wrap, .resultado-wrap, .just-wrap { margin-top: 0; }
|
||||
.penalidade-badge {
|
||||
font-size: 10px !important;
|
||||
font-weight: 700;
|
||||
padding: 2px 8px !important;
|
||||
border-radius: 999px;
|
||||
letter-spacing: 0.2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.penalidade-badge.label-danger { background: #f7dada; color: #9f2d2d; }
|
||||
.penalidade-badge.label-warning { background: #fff0c7; color: #8a5a00; }
|
||||
.penalidade-badge.label-info { background: #dceefe; color: #1f5f9b; }
|
||||
.penalidade-badge.label-success { background: #dff5e4; color: #1f7a3d; }
|
||||
.penalidade-badge.label-default { background: #eceff3; color: #5f6b7a; }
|
||||
.anexos-cell {
|
||||
background: #edf4fb;
|
||||
border: 1px solid #cfe0f3;
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
}
|
||||
.anexo-auto-hint { font-size: 11px; color: #5f7d9a; margin-top: 5px; }
|
||||
.anexo-progress {
|
||||
margin-top: 7px;
|
||||
font-size: 12px;
|
||||
color: #2d4f70;
|
||||
font-weight: 600;
|
||||
}
|
||||
.anexo-progress-count {
|
||||
display: inline-block;
|
||||
min-width: 40px;
|
||||
text-align: center;
|
||||
border-radius: 999px;
|
||||
background: #d9e9fa;
|
||||
color: #1d4f7c;
|
||||
padding: 1px 8px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.anexo-multi-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
||||
gap: 7px;
|
||||
}
|
||||
.audit-row[data-max-fotos="1"] .anexo-multi-list,
|
||||
.audit-row[data-max-fotos="2"] .anexo-multi-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.anexo-slot {
|
||||
background: #ffffff;
|
||||
border: 1px solid #c9dbef;
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
}
|
||||
.audit-row[data-max-fotos="1"] .anexo-slot,
|
||||
.audit-row[data-max-fotos="2"] .anexo-slot {
|
||||
max-width: 100%;
|
||||
}
|
||||
.anexo-slot.slot-filled {
|
||||
border-color: #8fc1a3;
|
||||
box-shadow: inset 0 0 0 1px rgba(79, 161, 109, 0.2);
|
||||
}
|
||||
.anexo-slot.extra-slot { display: none; }
|
||||
.anexo-multi-list.expanded .anexo-slot.extra-slot { display: block; }
|
||||
.anexo-slot-label {
|
||||
font-size: 11px;
|
||||
color: #4b5f74;
|
||||
margin-bottom: 3px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.anexo-toggle-wrap {
|
||||
margin-top: 8px;
|
||||
text-align: right;
|
||||
}
|
||||
.anexo-toggle {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #24557d !important;
|
||||
border-color: #b5cbe3;
|
||||
background: #f4f8fd;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent {
|
||||
width: 100%;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent input {
|
||||
height: 34px;
|
||||
border-color: #c7d8ec;
|
||||
background: #fff;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent .btn {
|
||||
height: 34px !important;
|
||||
min-width: 40px;
|
||||
}
|
||||
.just-wrap input {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.audit-row-target { background: #fff8e6 !important; }
|
||||
.nc-box {
|
||||
border: 1px solid #f5d0d0;
|
||||
background: #fff6f6;
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.nc-title {
|
||||
font-weight: 700;
|
||||
color: #9f2d2d;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.nc-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.nc-item {
|
||||
background: #fff;
|
||||
border: 1px solid #f1b7b7;
|
||||
color: #7f1d1d;
|
||||
border-radius: 999px;
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.anexo-view { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
||||
.anexo-thumb-inline {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
.anexo-file {
|
||||
font-size: 11px;
|
||||
max-width: 170px;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
background: #fafafa;
|
||||
}
|
||||
.anexo-text {
|
||||
background: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.section-title { font-size: 22px; }
|
||||
.progress-percent { font-size: 14px; min-width: 38px; }
|
||||
.progress-meta { font-size: 14px; }
|
||||
.instruction-title { font-size: 16px; }
|
||||
.instruction-steps { grid-template-columns: 1fr; font-size: 14px; }
|
||||
.audit-label { font-size: 13px; }
|
||||
.audit-input { height: 40px; font-size: 15px; }
|
||||
.audit-row-top { grid-template-columns: 1fr; }
|
||||
.meta-grid { grid-template-columns: repeat(2, minmax(100px, 1fr)); }
|
||||
.anexo-multi-list { grid-template-columns: 1fr; }
|
||||
#pilaresContainer { grid-template-columns: repeat(2, minmax(180px, 1fr)); }
|
||||
.pilar-panel.is-open { grid-column: auto; }
|
||||
.pilar-summary-card { grid-column: span 2; }
|
||||
.audit-send-wrap { padding: 8px 0 0 0; border-top: 0; }
|
||||
.audit-send-btn { width: 100%; }
|
||||
}
|
||||
1100
Auditoria/forms/auditoria_prototipo/assets/js/checklist.js
Normal file
1100
Auditoria/forms/auditoria_prototipo/assets/js/checklist.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,423 @@
|
||||
/**
|
||||
* Plugin JQuery para trabalhar com anexos nos formulários dentro do processo
|
||||
*
|
||||
* @author Bruno Gasparetto
|
||||
* @see https://github.com/brunogasparetto/fluig-form-attachment
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Configurações
|
||||
*
|
||||
* @typedef AttachmentSettings
|
||||
* @property {boolean} showActionButton Exibe o botão de upload/delete. True por padrão.
|
||||
* @property {boolean} filename Nome que será salvo como descrição do Anexo.
|
||||
* @property {boolean|string} prefixName Adiciona prefixo ao anexo. False por padrão, True para prefixo aleatório, String para prefixo fixo.
|
||||
* @property {string} accept Tipos de arquivos aceitos. Segue a regra do accept do input tipo file.
|
||||
*/
|
||||
|
||||
;(function ($) {
|
||||
"use strict";
|
||||
|
||||
const pluginName = "fluigFormAttachment";
|
||||
|
||||
const deleteFileClassName = "BtnDeleteFile";
|
||||
const uploadFileClassname = "BtnUploadFile";
|
||||
const viewerFileClassname = "BtnViewerFile";
|
||||
const compressedExtensions = [
|
||||
'.7z', '.zip', '.rar', '.gz', '.tar', '.tbz2', '.tgz', '.bz2', '.lz', '.lz4','.txz',
|
||||
'.xz', '.z', '.zst', '.zstd', '.war', '.ear', '.jar','.apk', '.arj', '.ace', '.cab',
|
||||
];
|
||||
|
||||
const isString = item => typeof item === "string";
|
||||
|
||||
/**
|
||||
* Procura o índice do anexo de acordo com sua descrição
|
||||
*
|
||||
* @param {string} filename
|
||||
* @returns {number} -1 se não encontrar
|
||||
*/
|
||||
const attachmentFindIndex = (filename) => parent.ECM.attachmentTable.getData().findIndex(attachment => attachment.description === filename);
|
||||
|
||||
/**
|
||||
* Configuração padrão
|
||||
*
|
||||
* @type {AttachmentSettings}
|
||||
*/
|
||||
const defaults = {
|
||||
showActionButton: true,
|
||||
filename: "Anexo",
|
||||
prefixName: false,
|
||||
accept: "*",
|
||||
};
|
||||
|
||||
class Plugin {
|
||||
/**
|
||||
* @type {AttachmentSettings}
|
||||
*/
|
||||
#settings;
|
||||
|
||||
/**
|
||||
* Elemento do arquivo. Pode ser um input ou span (no modo leitura).
|
||||
*
|
||||
* @type {JQuery<HTMLElement>}
|
||||
*/
|
||||
#input;
|
||||
|
||||
/**
|
||||
* @type {JQuery<HTMLElement>}
|
||||
*/
|
||||
#container;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
#attachmentFilename;
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element
|
||||
* @param {AttachmentSettings} options
|
||||
*/
|
||||
constructor(element, options) {
|
||||
|
||||
// Garantir um ID para o Input
|
||||
if (!element.id && element.nodeName.toLowerCase() === "input") {
|
||||
element.id = FLUIGC.utilities.randomUUID();
|
||||
}
|
||||
|
||||
this.#settings = $.extend({}, defaults, options);
|
||||
this.#input = $(element);
|
||||
this.#attachmentFilename = this.#input.val() || this.#input.text().trim();
|
||||
|
||||
this.#input
|
||||
.prop("readonly", true)
|
||||
.on("change", () => {
|
||||
this.#attachmentFilename = this.#input.val();
|
||||
this.#changeButtonsState();
|
||||
})
|
||||
.wrap(`<div class="${pluginName}Component"></div>`)
|
||||
.after(`<div class="${pluginName}Component_buttons">${this.#getButtonsTemplate()}</div>`);
|
||||
|
||||
this.#container = this.#input.closest(`.${pluginName}Component`);
|
||||
|
||||
this.#container
|
||||
.on("click", `.${pluginName}${deleteFileClassName}`, () => this.#confirmDeleteAttachment())
|
||||
.on("click", `.${pluginName}${uploadFileClassname}`, () => this.#uploadAttachment())
|
||||
.on("click", `.${pluginName}${viewerFileClassname}`, () => this.#viewAttachment())
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indica que o campo está válido
|
||||
*
|
||||
* Caso o campo possua algum valor é obrigatório que o anexo
|
||||
* esteja na tabela de anexos.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isValid() {
|
||||
return this.#attachmentFilename.length
|
||||
? this.hasAttachment()
|
||||
: true
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indica se o anexo está na tabela de anexos
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasAttachment() {
|
||||
const filename = this.#attachmentFilename || this.#input.val() || this.#input.text().trim();
|
||||
|
||||
return filename.length > 0 && attachmentFindIndex(filename) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove o anexo
|
||||
*
|
||||
* Método útil para excluir anexos em tabela Pai x Filho.
|
||||
*/
|
||||
deleteAttachment() {
|
||||
const attachmentIndex = parent.ECM.attachmentTable.getData().findIndex(
|
||||
attachment => attachment.description === this.#attachmentFilename
|
||||
);
|
||||
|
||||
setTimeout(() => this.#input.val("").trigger("change"), 500);
|
||||
|
||||
if (attachmentIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent.WKFViewAttachment.removeAttach([attachmentIndex]);
|
||||
}
|
||||
|
||||
showActionButton() {
|
||||
this.#settings.showActionButton = true;
|
||||
this.#input.trigger("change");
|
||||
}
|
||||
|
||||
hideActionButton() {
|
||||
this.#settings.showActionButton = false;
|
||||
this.#input.trigger("change");
|
||||
}
|
||||
|
||||
filename(fileName, prefixName) {
|
||||
if (fileName === undefined) {
|
||||
return this.#input.data("filename") || this.#settings.filename;
|
||||
}
|
||||
|
||||
this.#settings.filename = fileName;
|
||||
this.#input.data("filename", fileName);
|
||||
|
||||
if (prefixName !== undefined) {
|
||||
this.prefixName(prefixName);
|
||||
}
|
||||
}
|
||||
|
||||
prefixName(prefixName) {
|
||||
if (prefixName === undefined) {
|
||||
return this.#settings.prefixName;
|
||||
}
|
||||
|
||||
this.#settings.prefixName = prefixName;
|
||||
}
|
||||
|
||||
#getButtonsTemplate() {
|
||||
const hasFileSelected = this.#attachmentFilename.length !== 0;
|
||||
const canShowActionButton = this.#canDisplayActionButton();
|
||||
|
||||
return `<button type="button" class="${pluginName}BtnAction ${pluginName}${deleteFileClassName} btn btn-danger btn-sm ${(canShowActionButton && hasFileSelected) ? '' : 'hide'}" title="Remover Anexo"><i class="flaticon flaticon-trash icon-sm"></i></button>`
|
||||
+ `<button type="button" class="${pluginName}BtnAction ${pluginName}${uploadFileClassname} btn btn-success btn-sm ${(canShowActionButton && !hasFileSelected) ? '' : 'hide'}" title="Enviar Anexo"><i class="flaticon flaticon-upload icon-sm"></i></button>`
|
||||
+ `<button type="button" class="${pluginName}${viewerFileClassname} btn btn-info btn-sm ${hasFileSelected ? '' : 'hide'}" title="Visualizar Anexo"><i class="flaticon flaticon-view icon-sm"></i></button>`
|
||||
;
|
||||
}
|
||||
|
||||
#canDisplayActionButton() {
|
||||
const element = this.#input.get(0);
|
||||
|
||||
return this.#settings.showActionButton
|
||||
&& parent.ECM.workflowView.userPermissions.indexOf("P") >= 0
|
||||
&& location.href.includes('ManagerMode')
|
||||
&& !location.href.includes('token')
|
||||
&& element.nodeName.toLowerCase() === "input"
|
||||
&& !element.disabled
|
||||
;
|
||||
}
|
||||
|
||||
#changeButtonsState() {
|
||||
const hasFileSelected = this.#attachmentFilename.length !== 0;
|
||||
|
||||
if (this.#canDisplayActionButton()) {
|
||||
if (hasFileSelected) {
|
||||
this.#container.find(`.${pluginName}${uploadFileClassname}`).addClass("hide");
|
||||
this.#container.find(`.${pluginName}${deleteFileClassName}`).removeClass("hide");
|
||||
} else {
|
||||
this.#container.find(`.${pluginName}${deleteFileClassName}`).addClass("hide");
|
||||
this.#container.find(`.${pluginName}${uploadFileClassname}`).removeClass("hide");
|
||||
}
|
||||
} else {
|
||||
this.#container.find(`.${pluginName}BtnAction`).addClass("hide");
|
||||
}
|
||||
|
||||
if (hasFileSelected) {
|
||||
this.#container.find(`.${pluginName}${viewerFileClassname}`).removeClass("hide");
|
||||
} else {
|
||||
this.#container.find(`.${pluginName}${viewerFileClassname}`).addClass("hide");
|
||||
}
|
||||
}
|
||||
|
||||
#confirmDeleteAttachment() {
|
||||
if (!this.#canDisplayActionButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FLUIGC.message.confirm({
|
||||
message: `Deseja remover o anexo <b>${this.#attachmentFilename}</b>?`,
|
||||
title: 'Confirmação',
|
||||
labelYes: 'Sim, quero remover',
|
||||
labelNo: 'Não, quero cancelar',
|
||||
}, result => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deleteAttachment();
|
||||
});
|
||||
}
|
||||
|
||||
#uploadAttachment() {
|
||||
if (!this.#canDisplayActionButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let filename = this.#input.data("filename") || this.#settings.filename;
|
||||
|
||||
if (this.#settings.prefixName === true) {
|
||||
filename = FLUIGC.utilities.randomUUID().substring(0, 9) + filename;
|
||||
} else if (this.#settings.prefixName !== false && isString(this.#settings.prefixName)) {
|
||||
filename = `${this.#settings.prefixName}-${filename}`;
|
||||
}
|
||||
|
||||
// Evitar conflito de descrição do anexo
|
||||
if (attachmentFindIndex(filename) !== -1) {
|
||||
FLUIGC.toast({
|
||||
title: "Atenção",
|
||||
message: "Já existe um anexo com essa descrição",
|
||||
type: "warning",
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
parent.$("#ecm-navigation-inputFile-clone")
|
||||
.attr({
|
||||
"data-on-camera": "true",
|
||||
"data-file-name-camera": filename,
|
||||
"data-inputid": this.#input.attr("id"),
|
||||
"data-filename": filename,
|
||||
"multiple": false,
|
||||
"accept": this.#input.data("accept") || this.#settings.accept,
|
||||
})
|
||||
.trigger("click")
|
||||
;
|
||||
}
|
||||
|
||||
#viewAttachment() {
|
||||
const attachmentIndex = parent.ECM.attachmentTable.getData().findIndex(
|
||||
attachment => attachment.description === this.#attachmentFilename
|
||||
);
|
||||
|
||||
if (attachmentIndex === -1) {
|
||||
FLUIGC.toast({
|
||||
title: "Atenção",
|
||||
message: "Anexo não encontrado",
|
||||
type: "warning"
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const attachment = parent.ECM.attachmentTable.getRow(attachmentIndex);
|
||||
const physicalFileName = String(
|
||||
attachment.physicalFileName || attachment.fileName || attachment.name || ""
|
||||
).toLowerCase();
|
||||
const isCompressedFile = compressedExtensions.some(extension => physicalFileName.endsWith(extension));
|
||||
|
||||
if (attachment.documentId && !isCompressedFile) {
|
||||
parent.WKFViewAttachment.openAttachmentView(parent.WCMAPI.userCode, attachment.documentId, attachment.version);
|
||||
} else {
|
||||
parent.WKFViewAttachment.downloadAttach([attachmentIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instancia o Plugin ou executa algum método do plugin
|
||||
*
|
||||
* @param {AttachmentSettings|string} options
|
||||
* @returns {undefined|boolean|void}
|
||||
*/
|
||||
$.fn[pluginName] = function (options) {
|
||||
if (!parent.WKFViewAttachment || !parent.ECM || !parent.ECM.attachmentTable) {
|
||||
console.error(`Plugin ${pluginName} executado fora de um processo.`)
|
||||
return this;
|
||||
}
|
||||
|
||||
// Executa o Método
|
||||
if (isString(options)) {
|
||||
const methodName = options;
|
||||
const methodArgs = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
let returnedValue = undefined;
|
||||
|
||||
this.each(function () {
|
||||
let pluginData = $.data(this, pluginName);
|
||||
|
||||
if (!pluginData) {
|
||||
pluginData = new Plugin(this, {});
|
||||
$.data(this, pluginName, pluginData);
|
||||
}
|
||||
|
||||
if (!pluginData[methodName]) {
|
||||
return;
|
||||
}
|
||||
|
||||
returnedValue = pluginData[methodName](...methodArgs);
|
||||
|
||||
if (returnedValue !== undefined) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return returnedValue !== undefined
|
||||
? returnedValue
|
||||
: this
|
||||
;
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
if (!$.data(this, pluginName)) {
|
||||
$.data(this, pluginName, new Plugin(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!parent.WKFViewAttachment || !parent.ECM || !parent.ECM.attachmentTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loading = FLUIGC.loading(window, {
|
||||
title: "Aguarde",
|
||||
textMessage: "Enviando arquivo",
|
||||
})
|
||||
|
||||
$(() => {
|
||||
// Oculta aba anexos
|
||||
$("#tab-attachments", parent.document).hide();
|
||||
|
||||
parent.$("#ecm_navigation_fileupload")
|
||||
.on(`fileuploadadd.${pluginName}`, function(e, data) {
|
||||
// Impede abrir o Loading caso tenha erro no arquivo
|
||||
|
||||
const file = data.files[0];
|
||||
|
||||
if (parent.ECM.maxUploadSize > 0 && file.size >= (parent.ECM.maxUploadSize * 1024 * 1024)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent.ECM.newAttachmentsDocs.length
|
||||
&& parent.ECM.newAttachmentsDocs.findIndex(attachment => attachment.name === file.name) !== -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.show();
|
||||
})
|
||||
.on(`fileuploadfail.${pluginName}`, () => loading.hide())
|
||||
.on(`fileuploaddone.${pluginName}`, function() {
|
||||
// Atualiza o campo do arquivo caso o upload tenha ocorrido
|
||||
|
||||
loading.hide();
|
||||
|
||||
const btnUpload = parent.document.getElementById("ecm-navigation-inputFile-clone");
|
||||
const filename = btnUpload.getAttribute("data-filename");
|
||||
|
||||
if (attachmentFindIndex(filename) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(`#${btnUpload.getAttribute("data-inputid")}`).val(filename).trigger("change");
|
||||
});
|
||||
|
||||
parent.$(document).on(`fileuploadstop.${pluginName}`, () => loading.hide());
|
||||
});
|
||||
|
||||
|
||||
$("head").append(`<style>
|
||||
.${pluginName}Component { display: flex; align-items: center; flex-wrap: nowrap; }
|
||||
.${pluginName}Component input { border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; }
|
||||
.${pluginName}Component_buttons { display: flex; align-items: center; justify-content: flex-end; }
|
||||
.${pluginName}Component_buttons .btn { outline: none !important; outline-offset: unset !important; border-radius: 0 !important; height: 32px; }
|
||||
</style>`);
|
||||
|
||||
}(jQuery));
|
||||
1
Auditoria/forms/auditoria_prototipo/assets/js/fluigFormAttachment.min.js
vendored
Normal file
1
Auditoria/forms/auditoria_prototipo/assets/js/fluigFormAttachment.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
144
Auditoria/forms/auditoria_prototipo/auditoria_prototipo.html
Normal file
144
Auditoria/forms/auditoria_prototipo/auditoria_prototipo.html
Normal file
@ -0,0 +1,144 @@
|
||||
<html>
|
||||
<head>
|
||||
<link type="text/css" rel="stylesheet" href="/style-guide/css/fluig-style-guide.min.css" />
|
||||
<script type="text/javascript" src="/portal/resources/js/jquery/jquery.js"></script>
|
||||
<script type="text/javascript" src="/portal/resources/js/jquery/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="/portal/resources/js/mustache/mustache-min.js"></script>
|
||||
<script type="text/javascript" src="/style-guide/js/fluig-style-guide.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="./fluigFormAttachment.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="./assets/css/checklist.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="fluig-style-guide">
|
||||
<form name="form" role="form">
|
||||
<div class="container-fluid audit-shell">
|
||||
<div class="audit-status">
|
||||
<span class="status-pill" id="profileBadge">Perfil: Loja</span>
|
||||
<span class="status-pill" id="progressBadge">Evidências: 0/0</span>
|
||||
</div>
|
||||
|
||||
<h1 class="audit-main-title">Checklist de Auditoria dos Pilares</h1>
|
||||
|
||||
<section class="audit-section intro-data-section">
|
||||
<div class="instruction-section">
|
||||
<div class="instruction-copy">
|
||||
<div class="instruction-head">
|
||||
<div class="instruction-icon">i</div>
|
||||
<div class="instruction-title">Envie as fotos dos pilares</div>
|
||||
</div>
|
||||
<div class="instruction-steps">
|
||||
<span>1. Clique em um <strong>PILAR</strong></span>
|
||||
<span>3. Clique em <strong>ANEXAR</strong> para enviar a foto solicitada</span>
|
||||
<span>5. Envie para concluir</span>
|
||||
<span>2. Verifique as <strong>INSTRUÇÕES</strong></span>
|
||||
<span>4. Confira em <strong>VISUALIZAR</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="intro-divider"></div>
|
||||
|
||||
<div class="audit-context-card">
|
||||
<div class="section-title">Dados da Auditoria</div>
|
||||
<div class="row audit-context-row">
|
||||
<div class="col-md-2 col-sm-6">
|
||||
<label class="audit-label" for="loja">Loja</label>
|
||||
<input type="text" class="form-control audit-input" name="loja" id="loja" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-6">
|
||||
<label class="audit-label" for="responsavelLoja">Responsavel da Loja</label>
|
||||
<input type="text" class="form-control audit-input" name="responsavelLoja" id="responsavelLoja" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-6">
|
||||
<label class="audit-label" for="auditor">Analista</label>
|
||||
<input type="text" class="form-control audit-input" name="auditor" id="auditor" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-4">
|
||||
<label class="audit-label" for="dataAuditoria">Data</label>
|
||||
<input type="date" class="form-control audit-input" name="dataAuditoria" id="dataAuditoria" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-4">
|
||||
<label class="audit-label" for="ciclo">Ciclo</label>
|
||||
<input type="text" class="form-control audit-input" name="ciclo" id="ciclo" placeholder="Ex: 2026-03" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-4">
|
||||
<label class="audit-label" for="regional">Regional</label>
|
||||
<input type="text" class="form-control audit-input" name="regional" id="regional" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="nc-box" id="naoConformeBox" style="display:none;">
|
||||
<div class="nc-title">Pendências para correção</div>
|
||||
<div class="nc-list" id="naoConformeList"></div>
|
||||
</div>
|
||||
|
||||
<section class="audit-section progress-section">
|
||||
<h2 class="section-title">Progresso da Auditoria</h2>
|
||||
<div class="progress-inline">
|
||||
<div class="progress-track">
|
||||
<div class="progress-fill" id="globalProgressFill"></div>
|
||||
</div>
|
||||
<div class="progress-percent" id="globalProgressPercent">0%</div>
|
||||
</div>
|
||||
<div class="progress-meta" id="globalProgressMeta">0 de 0 fotos enviadas</div>
|
||||
</section>
|
||||
|
||||
<div class="row audit-card">
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="scoreFinal">0%</div>
|
||||
<small>Score final</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="pontosObtidos">0</div>
|
||||
<small>Pontos obtidos</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="pontosPossiveis">0</div>
|
||||
<small>Pontos possíveis</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="classificacao">-</div>
|
||||
<small>Classificação</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title pilares-title">Pilares Analisados</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="pilaresContainer"></div>
|
||||
</div>
|
||||
<div class="audit-send-wrap">
|
||||
<button type="button" class="btn btn-primary audit-send-btn" id="btnEnviarForm">Finalizar</button>
|
||||
</div>
|
||||
<input type="hidden" name="auditoriaPayload" id="auditoriaPayload" />
|
||||
<input type="hidden" name="temNaoConforme" id="temNaoConforme" value="false" />
|
||||
<input type="hidden" name="qtdNaoConforme" id="qtdNaoConforme" value="0" />
|
||||
<input type="hidden" name="listaNaoConforme" id="listaNaoConforme" value="" />
|
||||
<input type="hidden" name="saidaAnalise" id="saidaAnalise" value="CONFORME" />
|
||||
<input type="hidden" name="usuarioRetorno" id="usuarioRetorno" value="" />
|
||||
<input type="hidden" name="destinoLoja" id="destinoLoja" value="" />
|
||||
<input type="hidden" name="destinoLojaId" id="destinoLojaId" value="" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="./assets/js/checklist.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
208
Auditoria/workflow/scripts/beforeTaskSave.js
Normal file
208
Auditoria/workflow/scripts/beforeTaskSave.js
Normal file
@ -0,0 +1,208 @@
|
||||
function beforeTaskSave(colleagueId, nextSequenceId, userList) {
|
||||
var FORCE_EMAIL_DESTINATION = "";
|
||||
var currentState = parseInt(getValue("WKCurrentState"), 10);
|
||||
var nextState = parseInt(nextSequenceId, 10);
|
||||
|
||||
try {
|
||||
// Roteamento para loja na entrada da atividade "Validar Planograma" (task5).
|
||||
// Usa prioridade: destinoLojaId (colleagueId) -> destinoLoja (login).
|
||||
if (nextState === 5) {
|
||||
atribuiResponsavelLoja(userList);
|
||||
}
|
||||
} catch (eAssign) {
|
||||
log.error("[checklist][atribuicao] Falha ao atribuir responsavel da loja: " + eAssign);
|
||||
throw eAssign;
|
||||
}
|
||||
|
||||
// Notificacao por email so quando sai da atividade de analise (task5).
|
||||
if (currentState !== 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var saidaAnalise = (hAPI.getCardValue("saidaAnalise") || "").trim();
|
||||
var usuarioRetorno = (hAPI.getCardValue("usuarioRetorno") || "").trim();
|
||||
var destino = String(FORCE_EMAIL_DESTINATION || "").trim();
|
||||
var usuarioDestino = "";
|
||||
if (!destino) {
|
||||
usuarioDestino = usuarioRetorno || String(colleagueId || getValue("WKUser") || "").trim();
|
||||
destino = resolveEmailByColleagueId(usuarioDestino);
|
||||
}
|
||||
|
||||
log.info("[checklist][notificacao] saidaAnalise=" + saidaAnalise
|
||||
+ ", usuarioRetorno=" + usuarioRetorno
|
||||
+ ", colleagueId=" + colleagueId
|
||||
+ ", usuarioDestino=" + usuarioDestino
|
||||
+ ", destinoFinal=" + destino
|
||||
+ ", nextState=" + nextState);
|
||||
|
||||
if (!destino) {
|
||||
log.warn("[checklist][notificacao] Usuario destino nao informado.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidEmail(destino)) {
|
||||
log.warn("[checklist][notificacao] Email de destino invalido: " + destino);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextState === 9 || saidaAnalise === "NAO_CONFORME") {
|
||||
notificaPorTemplate("CHECKLIST_NAO_CONFORME", destino);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextState === 11 || saidaAnalise === "CONFORME") {
|
||||
notificaPorTemplate("CHECKLIST_CONFORME", destino);
|
||||
}
|
||||
} catch (e) {
|
||||
log.error("[checklist][notificacao] Falha ao disparar notificacao: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function atribuiResponsavelLoja(userList) {
|
||||
var destinoLojaId = String(hAPI.getCardValue("destinoLojaId") || "").trim();
|
||||
var destinoLojaLogin = String(hAPI.getCardValue("destinoLoja") || "").trim();
|
||||
var colleagueId = "";
|
||||
|
||||
if (destinoLojaId && existsActiveUserByColleagueId(destinoLojaId)) {
|
||||
colleagueId = destinoLojaId;
|
||||
}
|
||||
|
||||
if (!colleagueId && destinoLojaLogin) {
|
||||
colleagueId = resolveColleagueIdByLogin(destinoLojaLogin);
|
||||
}
|
||||
|
||||
if (!colleagueId) {
|
||||
throw "Preencha uma loja valida. destinoLojaId/destinoLoja nao encontrado no colleague ativo.";
|
||||
}
|
||||
|
||||
userList.clear();
|
||||
userList.add(colleagueId);
|
||||
hAPI.setCardValue("destinoLojaId", colleagueId);
|
||||
|
||||
log.info("[checklist][atribuicao] Responsavel definido. destinoLojaId=" + destinoLojaId
|
||||
+ ", destinoLoja=" + destinoLojaLogin
|
||||
+ ", colleagueIdFinal=" + colleagueId);
|
||||
}
|
||||
|
||||
function notificaPorTemplate(templateCode, destinatario) {
|
||||
var NOTIFIER_SENDER_USER = "admin";
|
||||
var recipients = new java.util.ArrayList();
|
||||
recipients.add(destinatario);
|
||||
|
||||
var parametros = new java.util.HashMap();
|
||||
parametros.put("numeroSolicitacao", String(getValue("WKNumProces") || ""));
|
||||
parametros.put("qtdNaoConforme", String(hAPI.getCardValue("qtdNaoConforme") || "0"));
|
||||
parametros.put("listaNaoConforme", String(hAPI.getCardValue("listaNaoConforme") || ""));
|
||||
parametros.put("loja", String(hAPI.getCardValue("loja") || ""));
|
||||
parametros.put("linkSolicitacao", montaLinkSolicitacao());
|
||||
|
||||
notifier.notify(
|
||||
NOTIFIER_SENDER_USER,
|
||||
templateCode,
|
||||
parametros,
|
||||
recipients,
|
||||
"text/html"
|
||||
);
|
||||
|
||||
log.info("[checklist][notificacao] Template " + templateCode + " enviado para " + destinatario);
|
||||
}
|
||||
|
||||
function montaLinkSolicitacao() {
|
||||
var server = String(getValue("WKServerURL") || "");
|
||||
var companyId = String(getValue("WKCompany") || "");
|
||||
var processId = String(getValue("WKNumProces") || "");
|
||||
if (!server || !companyId || !processId) {
|
||||
return "";
|
||||
}
|
||||
return server
|
||||
+ "/portal/p/"
|
||||
+ companyId
|
||||
+ "/pageworkflowview?app_ecm_workflowview_detailsProcessInstanceID="
|
||||
+ processId;
|
||||
}
|
||||
|
||||
function usuarioPossuiEmailValido(colleagueId) {
|
||||
try {
|
||||
var c1 = DatasetFactory.createConstraint("colleaguePK.colleagueId", colleagueId, colleagueId, ConstraintType.MUST);
|
||||
var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
var ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
|
||||
if (!ds || ds.rowsCount < 1) {
|
||||
log.warn("[checklist][notificacao] Usuario nao encontrado/inativo no colleague: " + colleagueId);
|
||||
return false;
|
||||
}
|
||||
var email = String(ds.getValue(0, "mail") || "").trim();
|
||||
log.info("[checklist][notificacao] Email encontrado para " + colleagueId + ": " + email);
|
||||
return email.indexOf("@") > 0;
|
||||
} catch (e) {
|
||||
log.error("[checklist][notificacao] Erro ao validar email do usuario " + colleagueId + ": " + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveEmailByColleagueId(colleagueId) {
|
||||
try {
|
||||
if (!colleagueId) {
|
||||
return "";
|
||||
}
|
||||
var ds = findColleagueByIdOrLogin(colleagueId);
|
||||
if (!ds || ds.rowsCount < 1) {
|
||||
log.warn("[checklist][notificacao] Usuario nao encontrado/inativo no colleague: " + colleagueId);
|
||||
return "";
|
||||
}
|
||||
var email = String(ds.getValue(0, "mail") || "").trim();
|
||||
log.info("[checklist][notificacao] Email encontrado para " + colleagueId + ": " + email);
|
||||
return email;
|
||||
} catch (e) {
|
||||
log.error("[checklist][notificacao] Erro ao buscar email do usuario " + colleagueId + ": " + e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function isValidEmail(email) {
|
||||
var v = String(email || "").trim();
|
||||
return v.indexOf("@") > 0 && v.indexOf(".") > v.indexOf("@") + 1;
|
||||
}
|
||||
|
||||
function existsActiveUserByColleagueId(colleagueId) {
|
||||
var ds = null;
|
||||
try {
|
||||
var c1 = DatasetFactory.createConstraint("colleaguePK.colleagueId", colleagueId, colleagueId, ConstraintType.MUST);
|
||||
var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
|
||||
return ds && ds.rowsCount > 0;
|
||||
} catch (e) {
|
||||
log.error("[checklist][atribuicao] Erro ao validar colleagueId=" + colleagueId + ": " + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveColleagueIdByLogin(login) {
|
||||
try {
|
||||
var c1 = DatasetFactory.createConstraint("login", login, login, ConstraintType.MUST);
|
||||
var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
var ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
|
||||
if (ds && ds.rowsCount > 0) {
|
||||
return String(ds.getValue(0, "colleaguePK.colleagueId") || "").trim();
|
||||
}
|
||||
} catch (e) {
|
||||
log.error("[checklist][atribuicao] Erro ao resolver colleagueId por login=" + login + ": " + e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function findColleagueByIdOrLogin(value) {
|
||||
var v = String(value || "").trim();
|
||||
if (!v) return null;
|
||||
var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
|
||||
var cId = DatasetFactory.createConstraint("colleaguePK.colleagueId", v, v, ConstraintType.MUST);
|
||||
var byId = DatasetFactory.getDataset("colleague", null, [cId, c2], null);
|
||||
if (byId && byId.rowsCount > 0) return byId;
|
||||
|
||||
var cLogin = DatasetFactory.createConstraint("login", v, v, ConstraintType.MUST);
|
||||
var byLogin = DatasetFactory.getDataset("colleague", null, [cLogin, c2], null);
|
||||
if (byLogin && byLogin.rowsCount > 0) return byLogin;
|
||||
|
||||
return null;
|
||||
}
|
||||
18
Auditoria_checklist/.project
Normal file
18
Auditoria_checklist/.project
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Auditoria_checklist</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
<nature>com.totvs.tds.ecm.designer.nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
108
Auditoria_checklist/.settings/org.eclipse.core.resources.prefs
Normal file
108
Auditoria_checklist/.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,108 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//wcm/layout/helloLayout/src/main/resources/application.info=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/resources/helloLayout.properties=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/resources/helloLayout_en_US.properties=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/resources/helloLayout_es.properties=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/resources/helloLayout_pt_BR.properties=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/resources/layout.ftl=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/webapp/resources/css/helloLayout.css=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/layout/helloLayout/src/main/webapp/resources/js/helloLayout.js=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/dashconforme.properties=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/dashconforme_en_US.properties=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/dashconforme_es.properties=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/dashconforme_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/webapp/resources/css/dashconforme.css=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/dashconforme/src/main/webapp/resources/js/dashconforme.js=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/dashdata.properties=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/dashdata_en_US.properties=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/dashdata_es.properties=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/dashdata_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/webapp/resources/css/dashdata.css=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/dashdata/src/main/webapp/resources/js/dashdata.js=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/dashgrafico.properties=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/dashgrafico_en_US.properties=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/dashgrafico_es.properties=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/dashgrafico_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/webapp/resources/css/dashgrafico.css=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/dashgrafico/src/main/webapp/resources/js/dashgrafico.js=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/dashkpi.properties=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/dashkpi_en_US.properties=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/dashkpi_es.properties=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/dashkpi_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/webapp/resources/css/dashkpi.css=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/dashkpi/src/main/webapp/resources/js/dashkpi.js=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/dashregional.properties=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/dashregional_en_US.properties=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/dashregional_es.properties=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/dashregional_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/webapp/resources/css/dashregional.css=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/dashregional/src/main/webapp/resources/js/dashregional.js=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/dashtabela.properties=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/dashtabela_en_US.properties=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/dashtabela_es.properties=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/dashtabela_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/webapp/resources/css/dashtabela.css=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/dashtabela/src/main/webapp/resources/js/dashtabela.js=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/filtrosDash.properties=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/filtrosDash_en_US.properties=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/filtrosDash_es.properties=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/filtrosDash_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/webapp/resources/css/filtrosDash.css=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/filtrosDash/src/main/webapp/resources/js/filtrosDash.js=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/application.info=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/edit.ftl=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/helloWidget.properties=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/helloWidget_en_US.properties=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/helloWidget_es.properties=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/helloWidget_pt_BR.properties=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/resources/view.ftl=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/webapp/WEB-INF/jboss-web.xml=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/webapp/WEB-INF/web.xml=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/webapp/resources/css/helloWidget.css=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/webapp/resources/images/icon.png=utf8
|
||||
encoding//wcm/widget/helloWidget/src/main/webapp/resources/js/helloWidget.js=utf8
|
||||
4
Auditoria_checklist/.vscode/servers.json
vendored
Normal file
4
Auditoria_checklist/.vscode/servers.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"configurations": []
|
||||
}
|
||||
151
Auditoria_checklist/datasets/ds_dashboard_checklist.js
Normal file
151
Auditoria_checklist/datasets/ds_dashboard_checklist.js
Normal file
@ -0,0 +1,151 @@
|
||||
function createDataset(fields, constraints, sortFields) {
|
||||
var ds = DatasetBuilder.newDataset();
|
||||
ds.addColumn("documentid");
|
||||
ds.addColumn("dataAuditoria");
|
||||
ds.addColumn("dataLimite");
|
||||
ds.addColumn("ciclo");
|
||||
ds.addColumn("auditor");
|
||||
ds.addColumn("usuarioRetorno");
|
||||
ds.addColumn("responsavelLoja");
|
||||
ds.addColumn("loja");
|
||||
ds.addColumn("regional");
|
||||
ds.addColumn("saidaAnalise");
|
||||
ds.addColumn("status");
|
||||
ds.addColumn("qtdNaoConforme");
|
||||
ds.addColumn("listaNaoConforme");
|
||||
|
||||
try {
|
||||
var filtros = parseConstraints(constraints);
|
||||
var formDs = DatasetFactory.getDataset("checklist", null, null, null);
|
||||
if (!formDs || formDs.rowsCount < 1) {
|
||||
return ds;
|
||||
}
|
||||
|
||||
var linhas = [];
|
||||
|
||||
for (var i = 0; i < formDs.rowsCount; i++) {
|
||||
var status = val(formDs, i, "saidaAnalise").toUpperCase();
|
||||
if (status !== "CONFORME" && status !== "NAO_CONFORME") {
|
||||
continue;
|
||||
}
|
||||
|
||||
var dataAuditoria = val(formDs, i, "dataAuditoria");
|
||||
var dataLimite = val(formDs, i, "dataLimite");
|
||||
var ciclo = val(formDs, i, "ciclo");
|
||||
var regional = val(formDs, i, "regional");
|
||||
var loja = val(formDs, i, "loja");
|
||||
|
||||
if (filtros.loja && norm(loja).indexOf(norm(filtros.loja)) === -1) {
|
||||
continue;
|
||||
}
|
||||
if (filtros.ciclo && norm(ciclo).indexOf(norm(filtros.ciclo)) === -1) {
|
||||
continue;
|
||||
}
|
||||
if (filtros.regional && norm(regional).indexOf(norm(filtros.regional)) === -1) {
|
||||
continue;
|
||||
}
|
||||
if (filtros.dataInicio || filtros.dataFim) {
|
||||
var faixaAuditoria = dataNaFaixa(dataAuditoria, filtros.dataInicio, filtros.dataFim);
|
||||
var faixaLimite = dataNaFaixa(dataLimite, filtros.dataInicio, filtros.dataFim);
|
||||
if (!faixaAuditoria && !faixaLimite) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
linhas.push({
|
||||
documentid: val(formDs, i, "documentid"),
|
||||
dataAuditoria: dataAuditoria,
|
||||
dataLimite: dataLimite,
|
||||
ciclo: ciclo,
|
||||
auditor: val(formDs, i, "auditor"),
|
||||
usuarioRetorno: val(formDs, i, "usuarioRetorno"),
|
||||
responsavelLoja: val(formDs, i, "responsavelLoja"),
|
||||
loja: loja,
|
||||
regional: regional,
|
||||
saidaAnalise: status,
|
||||
status: status,
|
||||
qtdNaoConforme: val(formDs, i, "qtdNaoConforme"),
|
||||
listaNaoConforme: val(formDs, i, "listaNaoConforme")
|
||||
});
|
||||
}
|
||||
|
||||
linhas.sort(function (a, b) {
|
||||
if (a.dataAuditoria < b.dataAuditoria) return 1;
|
||||
if (a.dataAuditoria > b.dataAuditoria) return -1;
|
||||
if (a.documentid < b.documentid) return 1;
|
||||
if (a.documentid > b.documentid) return -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
for (var j = 0; j < linhas.length; j++) {
|
||||
var r = linhas[j];
|
||||
ds.addRow([
|
||||
r.documentid,
|
||||
r.dataAuditoria,
|
||||
r.dataLimite,
|
||||
r.ciclo,
|
||||
r.auditor,
|
||||
r.usuarioRetorno,
|
||||
r.responsavelLoja,
|
||||
r.loja,
|
||||
r.regional,
|
||||
r.saidaAnalise,
|
||||
r.status,
|
||||
r.qtdNaoConforme,
|
||||
r.listaNaoConforme
|
||||
]);
|
||||
}
|
||||
} catch (e) {
|
||||
ds = DatasetBuilder.newDataset();
|
||||
ds.addColumn("ERRO");
|
||||
ds.addRow([String(e)]);
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
function parseConstraints(constraints) {
|
||||
var out = {
|
||||
dataInicio: "",
|
||||
dataFim: "",
|
||||
loja: "",
|
||||
ciclo: "",
|
||||
regional: ""
|
||||
};
|
||||
|
||||
if (!constraints) return out;
|
||||
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
var c = constraints[i];
|
||||
if (!c) continue;
|
||||
|
||||
var name = String(c.fieldName || c._field || "");
|
||||
var value = String(c.initialValue || c._initialValue || "").trim();
|
||||
if (!name || !value) continue;
|
||||
|
||||
if (name === "dataInicio") out.dataInicio = value;
|
||||
if (name === "dataFim") out.dataFim = value;
|
||||
if (name === "loja") out.loja = value;
|
||||
if (name === "ciclo") out.ciclo = value;
|
||||
if (name === "regional") out.regional = value;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function val(ds, row, col) {
|
||||
var v = ds.getValue(row, col);
|
||||
return String(v == null ? "" : v).trim();
|
||||
}
|
||||
|
||||
function norm(v) {
|
||||
return String(v || "").toLowerCase().trim();
|
||||
}
|
||||
|
||||
function dataNaFaixa(data, inicio, fim) {
|
||||
var d = String(data || "").trim();
|
||||
if (!d) return false;
|
||||
if (inicio && d < inicio) return false;
|
||||
if (fim && d > fim) return false;
|
||||
return true;
|
||||
}
|
||||
209
Auditoria_checklist/datasets/ds_lojas_api.js
Normal file
209
Auditoria_checklist/datasets/ds_lojas_api.js
Normal file
@ -0,0 +1,209 @@
|
||||
function createDataset(fields, constraints, sortFields) {
|
||||
var dataset = DatasetBuilder.newDataset();
|
||||
|
||||
dataset.addColumn("PDV");
|
||||
dataset.addColumn("LOJA");
|
||||
dataset.addColumn("RESPONSAVEL_LOJA");
|
||||
dataset.addColumn("REGIONAL");
|
||||
dataset.addColumn("UF");
|
||||
dataset.addColumn("CIDADE");
|
||||
dataset.addColumn("STATUS");
|
||||
dataset.addColumn("CANAL");
|
||||
dataset.addColumn("ID");
|
||||
dataset.addColumn("LOGIN_LOJA");
|
||||
dataset.addColumn("COLLEAGUE_ID");
|
||||
dataset.addColumn("USER_CREATE");
|
||||
|
||||
try {
|
||||
var clientService = fluigAPI.getAuthorizeClientService();
|
||||
var data = {
|
||||
companyId: String(getValue("WKCompany") || "1"),
|
||||
serviceCode: "GINSENG API", // ajuste para o codigo do servico cadastrado no Fluig
|
||||
endpoint: "/base_pdvs",
|
||||
method: "get",
|
||||
timeoutService: "60000",
|
||||
params: {}
|
||||
};
|
||||
|
||||
var vo = clientService.invoke(JSON.stringify(data));
|
||||
var statusHttp = vo ? String(vo.getHttpStatusResult() || "") : "";
|
||||
var retorno = vo ? String(vo.getResult() || "") : "";
|
||||
|
||||
if (!retorno) {
|
||||
dataset.addRow(["", "Sem resposta da API (HTTP " + statusHttp + ")", "", "", "", "", "", "", "", "", "", ""]);
|
||||
return dataset;
|
||||
}
|
||||
|
||||
var objData = JSON.parse(retorno);
|
||||
var success = !!objData.success;
|
||||
var itens = objData.data || [];
|
||||
|
||||
if (!success || !itens.length) {
|
||||
var msg = trim(objData.message) || trim(objData.error) || "Sem lojas retornadas";
|
||||
dataset.addRow(["", msg + " (HTTP " + statusHttp + ")", "", "", "", "", "", "", "", "", "", ""]);
|
||||
return dataset;
|
||||
}
|
||||
|
||||
var filtros = parseConstraints(constraints);
|
||||
var colleagueCache = {};
|
||||
|
||||
for (var i = 0; i < itens.length; i++) {
|
||||
var item = itens[i] || {};
|
||||
|
||||
var pdv = trim(item["PDV"]);
|
||||
var loja = trim(item["PDV DESC"]);
|
||||
var responsavel = trim(item["GESTAO"]) || trim(item["GESTAO"]);
|
||||
var regional = trim(item["SUPERVISOR"]) || trim(item["SUPERVISOR"]);
|
||||
var uf = trim(item["UF"]);
|
||||
var cidade = trim(item["CIDADE"]);
|
||||
var status = trim(item["STATUS"]);
|
||||
var canal = trim(item["CANAL"]);
|
||||
var id = trim(item["id"]);
|
||||
var loginLoja = pdv ? (pdv + ".ginseng") : "";
|
||||
var colleagueId = resolveColleagueIdByLogin(loginLoja);
|
||||
var userCreate = getUserCreateStatus(loginLoja, colleagueCache);
|
||||
|
||||
if (filtros.onlyAtivo && status.toUpperCase() !== "ATIVO") {
|
||||
continue;
|
||||
}
|
||||
if (filtros.pdv && pdv !== filtros.pdv) {
|
||||
continue;
|
||||
}
|
||||
if (filtros.loja && normalize(loja).indexOf(normalize(filtros.loja)) === -1) {
|
||||
continue;
|
||||
}
|
||||
if (filtros.termoLivre) {
|
||||
var blob = normalize([
|
||||
pdv,
|
||||
loja,
|
||||
responsavel,
|
||||
regional,
|
||||
uf,
|
||||
cidade
|
||||
].join(" "));
|
||||
if (blob.indexOf(normalize(filtros.termoLivre)) === -1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
dataset.addRow([
|
||||
pdv,
|
||||
loja,
|
||||
responsavel,
|
||||
regional,
|
||||
uf,
|
||||
cidade,
|
||||
status,
|
||||
canal,
|
||||
id,
|
||||
loginLoja,
|
||||
colleagueId,
|
||||
userCreate
|
||||
]);
|
||||
}
|
||||
|
||||
if (dataset.rowsCount === 0) {
|
||||
dataset.addRow(["", "Sem lojas apos filtros (HTTP " + statusHttp + ")", "", "", "", "", "", "", "", "", "", ""]);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
dataset = DatasetBuilder.newDataset();
|
||||
dataset.addColumn("ERRO");
|
||||
dataset.addRow([String(e)]);
|
||||
}
|
||||
|
||||
return dataset;
|
||||
}
|
||||
|
||||
function parseConstraints(constraints) {
|
||||
var out = {
|
||||
pdv: "",
|
||||
loja: "",
|
||||
onlyAtivo: true,
|
||||
termoLivre: ""
|
||||
};
|
||||
|
||||
if (!constraints) return out;
|
||||
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
var c = constraints[i];
|
||||
if (!c || !c.fieldName) continue;
|
||||
|
||||
var name = String(c.fieldName);
|
||||
var value = trim(c.initialValue);
|
||||
|
||||
if (name === "PDV" && value) out.pdv = value;
|
||||
if (name === "LOJA" && value) out.loja = value;
|
||||
if (name === "onlyAtivo" && value.toLowerCase() === "false") out.onlyAtivo = false;
|
||||
|
||||
// Zoom costuma enviar constraints variadas de busca; capturamos termo livre.
|
||||
if (
|
||||
value &&
|
||||
name !== "onlyAtivo" &&
|
||||
name !== "metadata#id" &&
|
||||
name !== "metadata#active" &&
|
||||
name !== "sqlLimit"
|
||||
) {
|
||||
var cleaned = cleanSearchValue(value);
|
||||
if (cleaned && (!out.termoLivre || cleaned.length > out.termoLivre.length)) {
|
||||
out.termoLivre = cleaned;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function trim(v) {
|
||||
return String(v == null ? "" : v).trim();
|
||||
}
|
||||
|
||||
function normalize(v) {
|
||||
return trim(v).toLowerCase();
|
||||
}
|
||||
|
||||
function cleanSearchValue(v) {
|
||||
var s = trim(v);
|
||||
// remove curingas comuns de busca do Zoom/like
|
||||
s = s.replace(/[%*_]/g, "");
|
||||
return trim(s);
|
||||
}
|
||||
|
||||
function getUserCreateStatus(loginLoja, cache) {
|
||||
var login = trim(loginLoja);
|
||||
if (!login) return "NAO";
|
||||
if (cache.hasOwnProperty(login)) return cache[login];
|
||||
try {
|
||||
var cLogin = DatasetFactory.createConstraint("login", login, login, ConstraintType.MUST);
|
||||
var cActive = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
var ds = DatasetFactory.getDataset("colleague", null, [cLogin, cActive], null);
|
||||
var exists = !!(ds && ds.rowsCount > 0);
|
||||
|
||||
// fallback para ambientes onde o identificador esta em colleagueId
|
||||
if (!exists) {
|
||||
var cId = DatasetFactory.createConstraint("colleaguePK.colleagueId", login, login, ConstraintType.MUST);
|
||||
ds = DatasetFactory.getDataset("colleague", null, [cId, cActive], null);
|
||||
exists = !!(ds && ds.rowsCount > 0);
|
||||
}
|
||||
|
||||
cache[login] = exists ? "OK" : "NAO";
|
||||
return cache[login];
|
||||
} catch (e) {
|
||||
cache[login] = "NAO";
|
||||
return "NAO";
|
||||
}
|
||||
}
|
||||
|
||||
function resolveColleagueIdByLogin(loginLoja) {
|
||||
var login = trim(loginLoja);
|
||||
if (!login) return "";
|
||||
try {
|
||||
var cLogin = DatasetFactory.createConstraint("login", login, login, ConstraintType.MUST);
|
||||
var cActive = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
|
||||
var ds = DatasetFactory.getDataset("colleague", null, [cLogin, cActive], null);
|
||||
if (ds && ds.rowsCount > 0) {
|
||||
return trim(ds.getValue(0, "colleaguePK.colleagueId"));
|
||||
}
|
||||
} catch (e) {}
|
||||
return "";
|
||||
}
|
||||
BIN
Auditoria_checklist/forms/40213 - checklist/.metadata
Normal file
BIN
Auditoria_checklist/forms/40213 - checklist/.metadata
Normal file
Binary file not shown.
@ -0,0 +1,640 @@
|
||||
body { background: #ffffff; }
|
||||
.audit-shell {
|
||||
background: #f4f8fd;
|
||||
border: 1px solid #dbe4ee;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 14px rgba(15, 23, 42, 0.06);
|
||||
padding: 10px 10px 14px 10px;
|
||||
margin: 14px auto 0 auto;
|
||||
max-width: 1140px;
|
||||
}
|
||||
.audit-section {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 14px;
|
||||
background: #ffffff;
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
h1.audit-main-title {
|
||||
margin: 2px 0 10px 0;
|
||||
font-size: 18px !important;
|
||||
line-height: 1.2;
|
||||
font-weight: 700 !important;
|
||||
color: #ffffff !important;
|
||||
background: #0b556b;
|
||||
border-radius: 10px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.section-title {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
}
|
||||
.audit-status {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin: 2px 0 10px 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.progress-section {
|
||||
padding: 5px 10px 5px 10px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.progress-section .section-title {
|
||||
font-size: 16px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.audit-context-card .section-title {
|
||||
font-size: 17px;
|
||||
}
|
||||
.progress-inline {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
.progress-track {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
border-radius: 999px;
|
||||
background: #e6ebf2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.progress-fill {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #3ea9c8 0%, #3ea9c8 100%);
|
||||
transition: width .18s ease-in-out;
|
||||
}
|
||||
.progress-percent {
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
color: #0f172a;
|
||||
font-weight: 700;
|
||||
min-width: 42px;
|
||||
text-align: right;
|
||||
}
|
||||
.progress-meta {
|
||||
margin-top: 3px;
|
||||
font-size: 9px;
|
||||
color: #52637b;
|
||||
font-weight: 600;
|
||||
}
|
||||
.instruction-section {
|
||||
display: block;
|
||||
background: #ffffff;
|
||||
}
|
||||
.intro-data-section {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(90deg, #f4f8fd 0%, #edf3fa 100%);
|
||||
}
|
||||
.intro-data-section .instruction-section {
|
||||
padding: 12px;
|
||||
border-radius: 14px 14px 0 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
.intro-divider {
|
||||
height: 1px;
|
||||
background: #dfe7f0;
|
||||
}
|
||||
.instruction-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.instruction-icon {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 999px;
|
||||
background: #3ea9c8;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
.instruction-title {
|
||||
font-size: 16px;
|
||||
color: #1f2f46;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.instruction-steps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(160px, 1fr));
|
||||
gap: 6px 16px;
|
||||
font-size: 10px;
|
||||
color: #334155;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.instruction-steps span {
|
||||
display: inline-block;
|
||||
border: 1px solid #b9d4ea;
|
||||
background: #f4f9ff;
|
||||
color: #0f3f66;
|
||||
border-radius: 999px;
|
||||
padding: 4px 9px;
|
||||
width: fit-content;
|
||||
}
|
||||
.status-pill {
|
||||
background: #eef5fb;
|
||||
border: 1px solid #d9e8f6;
|
||||
color: #0b556b;
|
||||
border-radius: 999px;
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.audit-context-card {
|
||||
background: #ffffff;
|
||||
padding: 12px;
|
||||
border-radius: 0 0 14px 14px;
|
||||
}
|
||||
.audit-context-row > div {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.audit-label {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.3px;
|
||||
color: #16486a;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.label-icon { opacity: 0.8; margin-right: 4px; }
|
||||
.audit-input {
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
border-color: #c9d7e7;
|
||||
border-radius: 7px;
|
||||
padding: 5px 9px;
|
||||
}
|
||||
.audit-input:focus {
|
||||
border-color: #74a5d3;
|
||||
box-shadow: 0 0 0 2px rgba(34, 93, 143, 0.12);
|
||||
}
|
||||
.audit-card { margin-top: 12px; }
|
||||
.audit-score { font-size: 22px; font-weight: 700; }
|
||||
.audit-score small { font-size: 12px; font-weight: 400; color: #7f8c8d; display: block; }
|
||||
#pilaresContainer {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(220px, 1fr));
|
||||
gap: 14px;
|
||||
background: #f4f8fd;
|
||||
border: 0;
|
||||
border-radius: 10px;
|
||||
padding: 8px 12px 10px 12px;
|
||||
}
|
||||
h2.section-title.pilares-title {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 17px !important;
|
||||
}
|
||||
.audit-send-wrap {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
padding: 10px 12px 2px 12px;
|
||||
border-top: 1px solid #dbe5f0;
|
||||
}
|
||||
.audit-send-btn {
|
||||
min-width: 120px;
|
||||
height: 38px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
background: #0b556b;
|
||||
border-color: #0b556b;
|
||||
}
|
||||
.audit-send-btn:hover,
|
||||
.audit-send-btn:focus {
|
||||
background: #0a4b5f;
|
||||
border-color: #0a4b5f;
|
||||
}
|
||||
.pilar-panel {
|
||||
border: 1px solid #d6e1ee;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
padding: 8px;
|
||||
min-height: 108px;
|
||||
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
|
||||
transition: box-shadow .18s ease, transform .18s ease;
|
||||
}
|
||||
.pilar-panel:hover {
|
||||
box-shadow: 0 10px 20px rgba(15, 23, 42, 0.12);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.pilar-panel.is-open {
|
||||
grid-column: 1 / -1;
|
||||
box-shadow: 0 12px 24px rgba(15, 23, 42, 0.14);
|
||||
}
|
||||
.pilar-summary-card {
|
||||
grid-column: span 3;
|
||||
border: 1px solid #d6e1ee;
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
padding: 10px 12px;
|
||||
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
.summary-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.summary-item {
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
color: #000000;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.summary-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.summary-name {
|
||||
color: #000000;
|
||||
font-weight: 700;
|
||||
}
|
||||
.pilar-head {
|
||||
background: #ffffff;
|
||||
border: 0;
|
||||
padding: 6px;
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
transition: background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
|
||||
}
|
||||
.pilar-head:hover {
|
||||
background: #f8fbff;
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
}
|
||||
.pilar-head.is-open {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.pilar-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.pilar-state-dot {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 999px;
|
||||
background: #94a3b8;
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
.pilar-state-dot.state-pending { background: #dc2626; border-color: rgba(220, 38, 38, 0.4); }
|
||||
.pilar-state-dot.state-progress { background: #d18a2f; border-color: rgba(209, 138, 47, 0.35); }
|
||||
.pilar-state-dot.state-done { background: #2f9d78; border-color: rgba(47, 157, 120, 0.35); }
|
||||
.pilar-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
.pilar-photo-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #243549;
|
||||
}
|
||||
.pilar-photo-count {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
color: #000000;
|
||||
}
|
||||
.pilar-missing {
|
||||
font-size: 10px;
|
||||
color: #000000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.pilar-mini-track {
|
||||
height: 5px;
|
||||
border-radius: 999px;
|
||||
background: #e4eaf1;
|
||||
overflow: hidden;
|
||||
}
|
||||
.pilar-mini-fill {
|
||||
display: block;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: #5d8fbe;
|
||||
transition: width .18s ease;
|
||||
}
|
||||
.pilar-foot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.pilar-count {
|
||||
font-size: 10px;
|
||||
color: #000000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.pilar-open-cta {
|
||||
font-size: 10px;
|
||||
color: #000000;
|
||||
font-weight: 700;
|
||||
}
|
||||
.pilar-body { padding: 8px 0 0 0; }
|
||||
.audit-row {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
margin: 0 0 12px 0;
|
||||
background: transparent;
|
||||
}
|
||||
.audit-row-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.audit-row-top {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
align-items: start;
|
||||
}
|
||||
.audit-info {
|
||||
min-width: 0;
|
||||
}
|
||||
.indicador-cell { font-weight: 700; color: #000000; font-size: 15px; line-height: 1.25; }
|
||||
.indicador-help {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
color: #5c6f82;
|
||||
line-height: 1.35;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
padding: 7px 9px;
|
||||
}
|
||||
.indicador-help ul {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
}
|
||||
.indicador-help li {
|
||||
margin: 2px 0;
|
||||
}
|
||||
.indicador-help .indicador-group {
|
||||
list-style: none;
|
||||
margin-top: 6px;
|
||||
margin-left: -18px;
|
||||
font-weight: 700;
|
||||
color: #36597b;
|
||||
}
|
||||
.indicador-help-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
||||
gap: 10px 20px;
|
||||
padding-left: 0;
|
||||
}
|
||||
.indicador-help-col .indicador-group {
|
||||
margin: 0 0 4px 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
.indicador-help-col ul {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
}
|
||||
.meta-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(100px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.meta-box {
|
||||
border: 1px solid #d7e2ef;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
padding: 8px 10px;
|
||||
min-height: 62px;
|
||||
}
|
||||
.meta-label { font-size: 11px; color: #64748b; text-transform: uppercase; }
|
||||
.meta-value { font-size: 20px; color: #1f2937; margin-top: 4px; font-weight: 600; }
|
||||
.meta-value .form-control {
|
||||
font-size: 14px;
|
||||
height: 34px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
.anexo-wrap, .resultado-wrap, .just-wrap { margin-top: 0; }
|
||||
.penalidade-badge {
|
||||
font-size: 10px !important;
|
||||
font-weight: 700;
|
||||
padding: 2px 8px !important;
|
||||
border-radius: 999px;
|
||||
letter-spacing: 0.2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.penalidade-badge.label-danger { background: #f7dada; color: #9f2d2d; }
|
||||
.penalidade-badge.label-warning { background: #fff0c7; color: #8a5a00; }
|
||||
.penalidade-badge.label-info { background: #dceefe; color: #1f5f9b; }
|
||||
.penalidade-badge.label-success { background: #dff5e4; color: #1f7a3d; }
|
||||
.penalidade-badge.label-default { background: #eceff3; color: #5f6b7a; }
|
||||
.anexos-cell {
|
||||
background: #eef3fb;
|
||||
border: 1px solid #cfdaea;
|
||||
border-radius: 14px;
|
||||
padding: 10px;
|
||||
}
|
||||
.anexo-auto-hint { font-size: 12px; color: #5c7390; margin-top: 7px; }
|
||||
.anexo-progress {
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
color: #26486a;
|
||||
font-weight: 600;
|
||||
}
|
||||
.anexo-progress-count {
|
||||
display: inline-block;
|
||||
min-width: 52px;
|
||||
text-align: center;
|
||||
border-radius: 999px;
|
||||
background: #d8e6f8;
|
||||
color: #204c7a;
|
||||
padding: 4px 12px;
|
||||
margin-right: 6px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.anexo-multi-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(240px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.audit-row[data-max-fotos="1"] .anexo-multi-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.audit-row[data-max-fotos="2"] .anexo-multi-list {
|
||||
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
||||
}
|
||||
.audit-row[data-max-fotos="3"] .anexo-multi-list {
|
||||
grid-template-columns: repeat(3, minmax(220px, 1fr));
|
||||
}
|
||||
.anexo-slot {
|
||||
background: #ffffff;
|
||||
border: 1px solid #bdcde1;
|
||||
border-radius: 10px;
|
||||
padding: 7px;
|
||||
position: relative;
|
||||
}
|
||||
.audit-row[data-max-fotos="1"] .anexo-slot,
|
||||
.audit-row[data-max-fotos="2"] .anexo-slot {
|
||||
max-width: 100%;
|
||||
}
|
||||
.anexo-slot.slot-filled {
|
||||
border-color: #8fc1a3;
|
||||
box-shadow: inset 0 0 0 1px rgba(79, 161, 109, 0.2);
|
||||
}
|
||||
.anexo-slot.extra-slot { display: none; }
|
||||
.anexo-multi-list.expanded .anexo-slot.extra-slot { display: block; }
|
||||
.anexo-slot-label {
|
||||
font-size: 12px;
|
||||
color: #375478;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.audit-row[data-max-fotos]:not([data-max-fotos="1"]) .anexo-slot::after {
|
||||
content: "•••";
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 8px;
|
||||
color: #b0c5df;
|
||||
font-size: 15px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
.anexo-toggle-wrap {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
.anexo-toggle {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #2f4f74 !important;
|
||||
border-color: #b7c8de;
|
||||
background: #eef3fb;
|
||||
border-radius: 12px;
|
||||
padding: 8px 22px;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent {
|
||||
width: 100%;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent input {
|
||||
height: 36px;
|
||||
border: 1px dashed #b6c9e1;
|
||||
border-radius: 8px;
|
||||
background: #eef3fb;
|
||||
font-size: 14px;
|
||||
color: #5e7898;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent input::placeholder {
|
||||
color: #8ea4bf;
|
||||
opacity: 1;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent .btn {
|
||||
height: 42px !important;
|
||||
min-width: 52px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent .btn-success {
|
||||
background: #2f81c6 !important;
|
||||
border-color: #2a75b3 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent .btn-default {
|
||||
background: #eef2f7 !important;
|
||||
border-color: #c7d1de !important;
|
||||
color: #41597a !important;
|
||||
}
|
||||
.anexos-cell .fluigFormAttachmentComponent .btn-danger {
|
||||
background: #e1574c !important;
|
||||
border-color: #d04c42 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.just-wrap input {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.audit-row-target { background: #fff8e6 !important; }
|
||||
.nc-box {
|
||||
border: 1px solid #f5d0d0;
|
||||
background: #fff6f6;
|
||||
border-radius: 10px;
|
||||
padding: 10px 12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.nc-title {
|
||||
font-weight: 700;
|
||||
color: #9f2d2d;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.nc-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.nc-item {
|
||||
background: #fff;
|
||||
border: 1px solid #f1b7b7;
|
||||
color: #7f1d1d;
|
||||
border-radius: 999px;
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.anexo-view { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
||||
.anexo-thumb-inline {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
object-fit: cover;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
.anexo-file {
|
||||
font-size: 11px;
|
||||
max-width: 170px;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
padding: 4px 6px;
|
||||
background: #fafafa;
|
||||
}
|
||||
.anexo-text {
|
||||
background: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.section-title { font-size: 22px; }
|
||||
.progress-percent { font-size: 14px; min-width: 38px; }
|
||||
.progress-meta { font-size: 14px; }
|
||||
.instruction-title { font-size: 16px; }
|
||||
.instruction-steps { grid-template-columns: 1fr; font-size: 14px; }
|
||||
.audit-label { font-size: 13px; }
|
||||
.audit-input { height: 40px; font-size: 15px; }
|
||||
.audit-row-top { grid-template-columns: 1fr; }
|
||||
.meta-grid { grid-template-columns: repeat(2, minmax(100px, 1fr)); }
|
||||
.anexo-multi-list { grid-template-columns: 1fr; }
|
||||
#pilaresContainer { grid-template-columns: repeat(2, minmax(180px, 1fr)); }
|
||||
.pilar-panel.is-open { grid-column: auto; }
|
||||
.pilar-summary-card { grid-column: span 2; }
|
||||
.audit-send-wrap { padding: 8px 0 0 0; border-top: 0; }
|
||||
.audit-send-btn { width: 100%; }
|
||||
}
|
||||
1175
Auditoria_checklist/forms/40213 - checklist/assets/js/checklist.js
Normal file
1175
Auditoria_checklist/forms/40213 - checklist/assets/js/checklist.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,423 @@
|
||||
/**
|
||||
* Plugin JQuery para trabalhar com anexos nos formulários dentro do processo
|
||||
*
|
||||
* @author Bruno Gasparetto
|
||||
* @see https://github.com/brunogasparetto/fluig-form-attachment
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Configurações
|
||||
*
|
||||
* @typedef AttachmentSettings
|
||||
* @property {boolean} showActionButton Exibe o botão de upload/delete. True por padrão.
|
||||
* @property {boolean} filename Nome que será salvo como descrição do Anexo.
|
||||
* @property {boolean|string} prefixName Adiciona prefixo ao anexo. False por padrão, True para prefixo aleatório, String para prefixo fixo.
|
||||
* @property {string} accept Tipos de arquivos aceitos. Segue a regra do accept do input tipo file.
|
||||
*/
|
||||
|
||||
;(function ($) {
|
||||
"use strict";
|
||||
|
||||
const pluginName = "fluigFormAttachment";
|
||||
|
||||
const deleteFileClassName = "BtnDeleteFile";
|
||||
const uploadFileClassname = "BtnUploadFile";
|
||||
const viewerFileClassname = "BtnViewerFile";
|
||||
const compressedExtensions = [
|
||||
'.7z', '.zip', '.rar', '.gz', '.tar', '.tbz2', '.tgz', '.bz2', '.lz', '.lz4','.txz',
|
||||
'.xz', '.z', '.zst', '.zstd', '.war', '.ear', '.jar','.apk', '.arj', '.ace', '.cab',
|
||||
];
|
||||
|
||||
const isString = item => typeof item === "string";
|
||||
|
||||
/**
|
||||
* Procura o índice do anexo de acordo com sua descrição
|
||||
*
|
||||
* @param {string} filename
|
||||
* @returns {number} -1 se não encontrar
|
||||
*/
|
||||
const attachmentFindIndex = (filename) => parent.ECM.attachmentTable.getData().findIndex(attachment => attachment.description === filename);
|
||||
|
||||
/**
|
||||
* Configuração padrão
|
||||
*
|
||||
* @type {AttachmentSettings}
|
||||
*/
|
||||
const defaults = {
|
||||
showActionButton: true,
|
||||
filename: "Anexo",
|
||||
prefixName: false,
|
||||
accept: "*",
|
||||
};
|
||||
|
||||
class Plugin {
|
||||
/**
|
||||
* @type {AttachmentSettings}
|
||||
*/
|
||||
#settings;
|
||||
|
||||
/**
|
||||
* Elemento do arquivo. Pode ser um input ou span (no modo leitura).
|
||||
*
|
||||
* @type {JQuery<HTMLElement>}
|
||||
*/
|
||||
#input;
|
||||
|
||||
/**
|
||||
* @type {JQuery<HTMLElement>}
|
||||
*/
|
||||
#container;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
#attachmentFilename;
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element
|
||||
* @param {AttachmentSettings} options
|
||||
*/
|
||||
constructor(element, options) {
|
||||
|
||||
// Garantir um ID para o Input
|
||||
if (!element.id && element.nodeName.toLowerCase() === "input") {
|
||||
element.id = FLUIGC.utilities.randomUUID();
|
||||
}
|
||||
|
||||
this.#settings = $.extend({}, defaults, options);
|
||||
this.#input = $(element);
|
||||
this.#attachmentFilename = this.#input.val() || this.#input.text().trim();
|
||||
|
||||
this.#input
|
||||
.prop("readonly", true)
|
||||
.on("change", () => {
|
||||
this.#attachmentFilename = this.#input.val();
|
||||
this.#changeButtonsState();
|
||||
})
|
||||
.wrap(`<div class="${pluginName}Component"></div>`)
|
||||
.after(`<div class="${pluginName}Component_buttons">${this.#getButtonsTemplate()}</div>`);
|
||||
|
||||
this.#container = this.#input.closest(`.${pluginName}Component`);
|
||||
|
||||
this.#container
|
||||
.on("click", `.${pluginName}${deleteFileClassName}`, () => this.#confirmDeleteAttachment())
|
||||
.on("click", `.${pluginName}${uploadFileClassname}`, () => this.#uploadAttachment())
|
||||
.on("click", `.${pluginName}${viewerFileClassname}`, () => this.#viewAttachment())
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indica que o campo está válido
|
||||
*
|
||||
* Caso o campo possua algum valor é obrigatório que o anexo
|
||||
* esteja na tabela de anexos.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isValid() {
|
||||
return this.#attachmentFilename.length
|
||||
? this.hasAttachment()
|
||||
: true
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indica se o anexo está na tabela de anexos
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasAttachment() {
|
||||
const filename = this.#attachmentFilename || this.#input.val() || this.#input.text().trim();
|
||||
|
||||
return filename.length > 0 && attachmentFindIndex(filename) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove o anexo
|
||||
*
|
||||
* Método útil para excluir anexos em tabela Pai x Filho.
|
||||
*/
|
||||
deleteAttachment() {
|
||||
const attachmentIndex = parent.ECM.attachmentTable.getData().findIndex(
|
||||
attachment => attachment.description === this.#attachmentFilename
|
||||
);
|
||||
|
||||
setTimeout(() => this.#input.val("").trigger("change"), 500);
|
||||
|
||||
if (attachmentIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent.WKFViewAttachment.removeAttach([attachmentIndex]);
|
||||
}
|
||||
|
||||
showActionButton() {
|
||||
this.#settings.showActionButton = true;
|
||||
this.#input.trigger("change");
|
||||
}
|
||||
|
||||
hideActionButton() {
|
||||
this.#settings.showActionButton = false;
|
||||
this.#input.trigger("change");
|
||||
}
|
||||
|
||||
filename(fileName, prefixName) {
|
||||
if (fileName === undefined) {
|
||||
return this.#input.data("filename") || this.#settings.filename;
|
||||
}
|
||||
|
||||
this.#settings.filename = fileName;
|
||||
this.#input.data("filename", fileName);
|
||||
|
||||
if (prefixName !== undefined) {
|
||||
this.prefixName(prefixName);
|
||||
}
|
||||
}
|
||||
|
||||
prefixName(prefixName) {
|
||||
if (prefixName === undefined) {
|
||||
return this.#settings.prefixName;
|
||||
}
|
||||
|
||||
this.#settings.prefixName = prefixName;
|
||||
}
|
||||
|
||||
#getButtonsTemplate() {
|
||||
const hasFileSelected = this.#attachmentFilename.length !== 0;
|
||||
const canShowActionButton = this.#canDisplayActionButton();
|
||||
|
||||
return `<button type="button" class="${pluginName}BtnAction ${pluginName}${deleteFileClassName} btn btn-danger btn-sm ${(canShowActionButton && hasFileSelected) ? '' : 'hide'}" title="Remover Anexo"><i class="flaticon flaticon-trash icon-sm"></i></button>`
|
||||
+ `<button type="button" class="${pluginName}BtnAction ${pluginName}${uploadFileClassname} btn btn-success btn-sm ${(canShowActionButton && !hasFileSelected) ? '' : 'hide'}" title="Enviar Anexo"><i class="flaticon flaticon-upload icon-sm"></i></button>`
|
||||
+ `<button type="button" class="${pluginName}${viewerFileClassname} btn btn-info btn-sm ${hasFileSelected ? '' : 'hide'}" title="Visualizar Anexo"><i class="flaticon flaticon-view icon-sm"></i></button>`
|
||||
;
|
||||
}
|
||||
|
||||
#canDisplayActionButton() {
|
||||
const element = this.#input.get(0);
|
||||
|
||||
return this.#settings.showActionButton
|
||||
&& parent.ECM.workflowView.userPermissions.indexOf("P") >= 0
|
||||
&& location.href.includes('ManagerMode')
|
||||
&& !location.href.includes('token')
|
||||
&& element.nodeName.toLowerCase() === "input"
|
||||
&& !element.disabled
|
||||
;
|
||||
}
|
||||
|
||||
#changeButtonsState() {
|
||||
const hasFileSelected = this.#attachmentFilename.length !== 0;
|
||||
|
||||
if (this.#canDisplayActionButton()) {
|
||||
if (hasFileSelected) {
|
||||
this.#container.find(`.${pluginName}${uploadFileClassname}`).addClass("hide");
|
||||
this.#container.find(`.${pluginName}${deleteFileClassName}`).removeClass("hide");
|
||||
} else {
|
||||
this.#container.find(`.${pluginName}${deleteFileClassName}`).addClass("hide");
|
||||
this.#container.find(`.${pluginName}${uploadFileClassname}`).removeClass("hide");
|
||||
}
|
||||
} else {
|
||||
this.#container.find(`.${pluginName}BtnAction`).addClass("hide");
|
||||
}
|
||||
|
||||
if (hasFileSelected) {
|
||||
this.#container.find(`.${pluginName}${viewerFileClassname}`).removeClass("hide");
|
||||
} else {
|
||||
this.#container.find(`.${pluginName}${viewerFileClassname}`).addClass("hide");
|
||||
}
|
||||
}
|
||||
|
||||
#confirmDeleteAttachment() {
|
||||
if (!this.#canDisplayActionButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FLUIGC.message.confirm({
|
||||
message: `Deseja remover o anexo <b>${this.#attachmentFilename}</b>?`,
|
||||
title: 'Confirmação',
|
||||
labelYes: 'Sim, quero remover',
|
||||
labelNo: 'Não, quero cancelar',
|
||||
}, result => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deleteAttachment();
|
||||
});
|
||||
}
|
||||
|
||||
#uploadAttachment() {
|
||||
if (!this.#canDisplayActionButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let filename = this.#input.data("filename") || this.#settings.filename;
|
||||
|
||||
if (this.#settings.prefixName === true) {
|
||||
filename = FLUIGC.utilities.randomUUID().substring(0, 9) + filename;
|
||||
} else if (this.#settings.prefixName !== false && isString(this.#settings.prefixName)) {
|
||||
filename = `${this.#settings.prefixName}-${filename}`;
|
||||
}
|
||||
|
||||
// Evitar conflito de descrição do anexo
|
||||
if (attachmentFindIndex(filename) !== -1) {
|
||||
FLUIGC.toast({
|
||||
title: "Atenção",
|
||||
message: "Já existe um anexo com essa descrição",
|
||||
type: "warning",
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
parent.$("#ecm-navigation-inputFile-clone")
|
||||
.attr({
|
||||
"data-on-camera": "true",
|
||||
"data-file-name-camera": filename,
|
||||
"data-inputid": this.#input.attr("id"),
|
||||
"data-filename": filename,
|
||||
"multiple": false,
|
||||
"accept": this.#input.data("accept") || this.#settings.accept,
|
||||
})
|
||||
.trigger("click")
|
||||
;
|
||||
}
|
||||
|
||||
#viewAttachment() {
|
||||
const attachmentIndex = parent.ECM.attachmentTable.getData().findIndex(
|
||||
attachment => attachment.description === this.#attachmentFilename
|
||||
);
|
||||
|
||||
if (attachmentIndex === -1) {
|
||||
FLUIGC.toast({
|
||||
title: "Atenção",
|
||||
message: "Anexo não encontrado",
|
||||
type: "warning"
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const attachment = parent.ECM.attachmentTable.getRow(attachmentIndex);
|
||||
const physicalFileName = String(
|
||||
attachment.physicalFileName || attachment.fileName || attachment.name || ""
|
||||
).toLowerCase();
|
||||
const isCompressedFile = compressedExtensions.some(extension => physicalFileName.endsWith(extension));
|
||||
|
||||
if (attachment.documentId && !isCompressedFile) {
|
||||
parent.WKFViewAttachment.openAttachmentView(parent.WCMAPI.userCode, attachment.documentId, attachment.version);
|
||||
} else {
|
||||
parent.WKFViewAttachment.downloadAttach([attachmentIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instancia o Plugin ou executa algum método do plugin
|
||||
*
|
||||
* @param {AttachmentSettings|string} options
|
||||
* @returns {undefined|boolean|void}
|
||||
*/
|
||||
$.fn[pluginName] = function (options) {
|
||||
if (!parent.WKFViewAttachment || !parent.ECM || !parent.ECM.attachmentTable) {
|
||||
console.error(`Plugin ${pluginName} executado fora de um processo.`)
|
||||
return this;
|
||||
}
|
||||
|
||||
// Executa o Método
|
||||
if (isString(options)) {
|
||||
const methodName = options;
|
||||
const methodArgs = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
let returnedValue = undefined;
|
||||
|
||||
this.each(function () {
|
||||
let pluginData = $.data(this, pluginName);
|
||||
|
||||
if (!pluginData) {
|
||||
pluginData = new Plugin(this, {});
|
||||
$.data(this, pluginName, pluginData);
|
||||
}
|
||||
|
||||
if (!pluginData[methodName]) {
|
||||
return;
|
||||
}
|
||||
|
||||
returnedValue = pluginData[methodName](...methodArgs);
|
||||
|
||||
if (returnedValue !== undefined) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return returnedValue !== undefined
|
||||
? returnedValue
|
||||
: this
|
||||
;
|
||||
}
|
||||
|
||||
return this.each(function () {
|
||||
if (!$.data(this, pluginName)) {
|
||||
$.data(this, pluginName, new Plugin(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!parent.WKFViewAttachment || !parent.ECM || !parent.ECM.attachmentTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loading = FLUIGC.loading(window, {
|
||||
title: "Aguarde",
|
||||
textMessage: "Enviando arquivo",
|
||||
})
|
||||
|
||||
$(() => {
|
||||
// Oculta aba anexos
|
||||
$("#tab-attachments", parent.document).hide();
|
||||
|
||||
parent.$("#ecm_navigation_fileupload")
|
||||
.on(`fileuploadadd.${pluginName}`, function(e, data) {
|
||||
// Impede abrir o Loading caso tenha erro no arquivo
|
||||
|
||||
const file = data.files[0];
|
||||
|
||||
if (parent.ECM.maxUploadSize > 0 && file.size >= (parent.ECM.maxUploadSize * 1024 * 1024)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent.ECM.newAttachmentsDocs.length
|
||||
&& parent.ECM.newAttachmentsDocs.findIndex(attachment => attachment.name === file.name) !== -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.show();
|
||||
})
|
||||
.on(`fileuploadfail.${pluginName}`, () => loading.hide())
|
||||
.on(`fileuploaddone.${pluginName}`, function() {
|
||||
// Atualiza o campo do arquivo caso o upload tenha ocorrido
|
||||
|
||||
loading.hide();
|
||||
|
||||
const btnUpload = parent.document.getElementById("ecm-navigation-inputFile-clone");
|
||||
const filename = btnUpload.getAttribute("data-filename");
|
||||
|
||||
if (attachmentFindIndex(filename) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(`#${btnUpload.getAttribute("data-inputid")}`).val(filename).trigger("change");
|
||||
});
|
||||
|
||||
parent.$(document).on(`fileuploadstop.${pluginName}`, () => loading.hide());
|
||||
});
|
||||
|
||||
|
||||
$("head").append(`<style>
|
||||
.${pluginName}Component { display: flex; align-items: center; flex-wrap: nowrap; }
|
||||
.${pluginName}Component input { border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; }
|
||||
.${pluginName}Component_buttons { display: flex; align-items: center; justify-content: flex-end; }
|
||||
.${pluginName}Component_buttons .btn { outline: none !important; outline-offset: unset !important; border-radius: 0 !important; height: 32px; }
|
||||
</style>`);
|
||||
|
||||
}(jQuery));
|
||||
1
Auditoria_checklist/forms/40213 - checklist/assets/js/fluigFormAttachment.min.js
vendored
Normal file
1
Auditoria_checklist/forms/40213 - checklist/assets/js/fluigFormAttachment.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,166 @@
|
||||
<html>
|
||||
<head>
|
||||
<link type="text/css" rel="stylesheet" href="/style-guide/css/fluig-style-guide.min.css" />
|
||||
<script type="text/javascript" src="/portal/resources/js/jquery/jquery.js"></script>
|
||||
<script type="text/javascript" src="/portal/resources/js/jquery/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="/portal/resources/js/mustache/mustache-min.js"></script>
|
||||
<script type="text/javascript" src="/style-guide/js/fluig-style-guide.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="./fluigFormAttachment.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="./assets/css/checklist.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="fluig-style-guide">
|
||||
<form name="form" role="form">
|
||||
<div class="container-fluid audit-shell">
|
||||
<div class="audit-status">
|
||||
<span class="status-pill" id="profileBadge">Perfil: Loja</span>
|
||||
<span class="status-pill" id="progressBadge">Evidências: 0/0</span>
|
||||
</div>
|
||||
|
||||
<h1 class="audit-main-title">Checklist de Auditoria dos Pilares</h1>
|
||||
|
||||
<section class="audit-section intro-data-section">
|
||||
<div class="instruction-section">
|
||||
<div class="instruction-copy">
|
||||
<div class="instruction-head">
|
||||
<div class="instruction-icon">i</div>
|
||||
<div class="instruction-title">Envie as fotos dos pilares</div>
|
||||
</div>
|
||||
<div class="instruction-steps">
|
||||
<span>1. Clique em um <strong>PILAR</strong></span>
|
||||
<span>3. Clique em <strong>ANEXAR</strong> para enviar a foto solicitada</span>
|
||||
<span>5. Envie para concluir</span>
|
||||
<span>2. Verifique as <strong>INSTRUÇÕES</strong></span>
|
||||
<span>4. Confira em <strong>VISUALIZAR</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="intro-divider"></div>
|
||||
|
||||
<div class="audit-context-card">
|
||||
<div class="section-title">Dados da Auditoria</div>
|
||||
<div class="row audit-context-row">
|
||||
<div class="col-md-6 col-sm-6">
|
||||
<label class="audit-label" for="loja">Loja</label>
|
||||
<input
|
||||
type="zoom"
|
||||
class="form-control audit-input"
|
||||
name="loja"
|
||||
id="loja"
|
||||
data-zoom="{
|
||||
'displayKey':'LOJA',
|
||||
'datasetId':'ds_lojas_api',
|
||||
'maximumSelectionLength':'1',
|
||||
'placeholder':'Selecione a loja',
|
||||
'fields':[
|
||||
{'field':'LOJA','label':'Loja', 'standard':'true','search':'true'},
|
||||
{'field':'RESPONSAVEL_LOJA','label':'Responsavel'},
|
||||
{'field':'REGIONAL','label':'Regional'},
|
||||
{'field':'COLLEAGUE_ID','label':'Colleague ID'},
|
||||
{'field':'LOGIN_LOJA','label':'Login Loja'}
|
||||
]
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6">
|
||||
<label class="audit-label" for="responsavelLoja">Responsavel da Loja</label>
|
||||
<input type="text" class="form-control audit-input" name="responsavelLoja" id="responsavelLoja" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-6">
|
||||
<label class="audit-label" for="auditor">Analista</label>
|
||||
<input type="text" class="form-control audit-input" name="auditor" id="auditor" />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-4">
|
||||
<label class="audit-label" for="dataAuditoria">Data</label>
|
||||
<input type="date" class="form-control audit-input" name="dataAuditoria" id="dataAuditoria" readonly/>
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-4">
|
||||
<label class="audit-label" for="ciclo">Ciclo</label>
|
||||
<input type="text" class="form-control audit-input" name="ciclo" id="ciclo" placeholder="Ex: 2026-03" required />
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-4">
|
||||
<label class="audit-label" for="regional">Regional</label>
|
||||
<input type="text" class="form-control audit-input" name="regional" id="regional" readonly />
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-4">
|
||||
<label class="audit-label" for="dataLimite">Data limite</label>
|
||||
<input type="date" class="form-control audit-input" name="dataLimite" id="dataLimite" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="nc-box" id="naoConformeBox" style="display:none;">
|
||||
<div class="nc-title">Pendências para correção</div>
|
||||
<div class="nc-list" id="naoConformeList"></div>
|
||||
</div>
|
||||
|
||||
<section class="audit-section progress-section">
|
||||
<h2 class="section-title">Progresso da Auditoria</h2>
|
||||
<div class="progress-inline">
|
||||
<div class="progress-track">
|
||||
<div class="progress-fill" id="globalProgressFill"></div>
|
||||
</div>
|
||||
<div class="progress-percent" id="globalProgressPercent">0%</div>
|
||||
</div>
|
||||
<div class="progress-meta" id="globalProgressMeta">0 de 0 fotos enviadas</div>
|
||||
</section>
|
||||
|
||||
<div class="row audit-card">
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="scoreFinal">0%</div>
|
||||
<small>Score final</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="pontosObtidos">0</div>
|
||||
<small>Pontos obtidos</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="pontosPossiveis">0</div>
|
||||
<small>Pontos possíveis</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="audit-score" id="classificacao">-</div>
|
||||
<small>Classificação</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title pilares-title">Pilares Analisados</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="pilaresContainer"></div>
|
||||
</div>
|
||||
<div class="audit-send-wrap">
|
||||
<button type="button" class="btn btn-primary audit-send-btn" id="btnEnviarForm">Finalizar</button>
|
||||
</div>
|
||||
<input type="hidden" name="auditoriaPayload" id="auditoriaPayload" />
|
||||
<input type="hidden" name="temNaoConforme" id="temNaoConforme" value="false" />
|
||||
<input type="hidden" name="qtdNaoConforme" id="qtdNaoConforme" value="0" />
|
||||
<input type="hidden" name="listaNaoConforme" id="listaNaoConforme" value="" />
|
||||
<input type="hidden" name="saidaAnalise" id="saidaAnalise" value="CONFORME" />
|
||||
<input type="hidden" name="usuarioRetorno" id="usuarioRetorno" value="" />
|
||||
<input type="hidden" name="destinoLoja" id="destinoLoja" value="" />
|
||||
<input type="hidden" name="destinoLojaId" id="destinoLojaId" value="" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="./assets/js/checklist.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
32
Auditoria_checklist/templates/email/CHECKLIST_CONFORME.html
Normal file
32
Auditoria_checklist/templates/email/CHECKLIST_CONFORME.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Checklist Aprovado</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; background: #f4f6f8; margin: 0; padding: 24px; color: #1f2937; }
|
||||
.card { max-width: 720px; margin: 0 auto; background: #ffffff; border: 1px solid #e5e7eb; border-radius: 10px; overflow: hidden; }
|
||||
.head { background: #1f7a3d; color: #fff; padding: 14px 18px; font-size: 18px; font-weight: 700; }
|
||||
.body { padding: 18px; font-size: 14px; line-height: 1.5; }
|
||||
.meta { margin: 10px 0; padding: 10px 12px; background: #f5fbf7; border: 1px solid #d5ecd9; border-radius: 8px; }
|
||||
.label { font-weight: 700; }
|
||||
.footer { margin-top: 14px; font-size: 12px; color: #6b7280; }
|
||||
a.btn { display: inline-block; margin-top: 12px; background: #1369a8; color: #fff !important; text-decoration: none; padding: 9px 14px; border-radius: 6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="head">Checklist aprovado</div>
|
||||
<div class="body">
|
||||
<p>O checklist <b>${numeroSolicitacao}</b> foi aprovado como conforme.</p>
|
||||
<div class="meta">
|
||||
<div><span class="label">Loja:</span> ${loja}</div>
|
||||
<div><span class="label">Status:</span> Conforme</div>
|
||||
</div>
|
||||
<a class="btn" href="${linkSolicitacao}">Abrir solicitacao</a>
|
||||
<div class="footer">Mensagem automatica do processo de checklist.</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Checklist com Pendencias</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; background: #f4f6f8; margin: 0; padding: 24px; color: #1f2937; }
|
||||
.card { max-width: 720px; margin: 0 auto; background: #ffffff; border: 1px solid #e5e7eb; border-radius: 10px; overflow: hidden; }
|
||||
.head { background: #9f2d2d; color: #fff; padding: 14px 18px; font-size: 18px; font-weight: 700; }
|
||||
.body { padding: 18px; font-size: 14px; line-height: 1.5; }
|
||||
.meta { margin: 10px 0; padding: 10px 12px; background: #fff8f8; border: 1px solid #f3d3d3; border-radius: 8px; }
|
||||
.label { font-weight: 700; }
|
||||
.footer { margin-top: 14px; font-size: 12px; color: #6b7280; }
|
||||
a.btn { display: inline-block; margin-top: 12px; background: #1369a8; color: #fff !important; text-decoration: none; padding: 9px 14px; border-radius: 6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<div class="head">Checklist com pendencias de correcao</div>
|
||||
<div class="body">
|
||||
<p>O checklist <b>${numeroSolicitacao}</b> foi analisado e retornou para correcao.</p>
|
||||
<div class="meta">
|
||||
<div><span class="label">Loja:</span> ${loja}</div>
|
||||
<div><span class="label">Qtd. nao conforme:</span> ${qtdNaoConforme}</div>
|
||||
<div><span class="label">Itens:</span> ${listaNaoConforme}</div>
|
||||
</div>
|
||||
<p>Revise os itens e anexe as evidencias corrigidas.</p>
|
||||
<a class="btn" href="${linkSolicitacao}">Abrir solicitacao</a>
|
||||
<div class="footer">Mensagem automatica do processo de checklist.</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,23 @@
|
||||
application.type=layout
|
||||
application.code=helloLayout
|
||||
application.title=helloLayout
|
||||
application.description=helloLayout
|
||||
application.fluig.version=null
|
||||
application.category=SYSTEM
|
||||
application.renderer=freemarker
|
||||
developer.code=andrey.cunha
|
||||
developer.name=andrey.cunha
|
||||
developer.url=http://www.fluig.com
|
||||
layout.defaultSlot=SlotA
|
||||
layout.file=layout.ftl
|
||||
locale.file.base.name=helloLayout
|
||||
slot.SlotGlobalAlert=alertpopover
|
||||
slot.SlotInstantSearch=suggestsearch
|
||||
slot.SlotLogin=sociallogin
|
||||
slot.SlotMenu=menu
|
||||
slot.SlotUsePolicy=usepolicy
|
||||
application.icon=icon.png
|
||||
application.resource.css.1=/portal/resources/css/wcm_responsive_layout.css
|
||||
application.responsiveLayout=true
|
||||
application.newBuilder=true
|
||||
hash=4a16315e9e66fa7d797b3f6b1fb365b69f9a4ce2
|
||||
@ -0,0 +1 @@
|
||||
application.title=applicationTitle
|
||||
@ -0,0 +1 @@
|
||||
application.title=applicationTitle
|
||||
@ -0,0 +1 @@
|
||||
application.title=applicationTitle
|
||||
@ -0,0 +1 @@
|
||||
application.title=applicationTitle
|
||||
@ -0,0 +1,41 @@
|
||||
<#import "/wcm.ftl" as wcm />
|
||||
|
||||
<#-- Variaveis globais para os layouts -->
|
||||
<#import "/layout-globals.ftl" as globals />
|
||||
|
||||
<!-- layout ECM-DEFAULT-DASHBOARD -->
|
||||
|
||||
<#if pageRender.isPreviewMode() = true>
|
||||
<@wcm.previewPageAlert />
|
||||
<@wcm.deviceTogglePreview />
|
||||
</#if>
|
||||
|
||||
<div class="wcm-wrapper-content ${wcmLayoutEditClass!""} ${pageAuthTypeClass!""}">
|
||||
|
||||
<#if pageRender.isEditMode() != true>
|
||||
<@wcm.header />
|
||||
<@wcm.menu />
|
||||
</#if>
|
||||
|
||||
<div class="wcm-all-content">
|
||||
|
||||
<div id="wcm-content" class="clearfix wcm-background">
|
||||
|
||||
<#if pageRender.isEditMode() = true>
|
||||
<@wcm.editHeader />
|
||||
<@wcm.widgetsList />
|
||||
</#if>
|
||||
|
||||
<div id="${divMasterId!""}" class="clearfix">
|
||||
|
||||
<!-- Conteúdo aqui -->
|
||||
|
||||
|
||||
<#if fluigThemeCode != "responsive_theme">
|
||||
<@wcm.footer layoutuserlabel="wcm.layoutdefaultecmdashboard.user" />
|
||||
</#if>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web>
|
||||
<context-root>/helloLayout</context-root>
|
||||
<disable-cross-context>false</disable-cross-context>
|
||||
</jboss-web>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
</web-app>
|
||||
@ -0,0 +1 @@
|
||||
/*insira aqui seu código CSS*/
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 587 B |
@ -0,0 +1,2 @@
|
||||
// Insira aqui seu codigo JavaScript
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
application.type=widget
|
||||
application.code=dashconforme
|
||||
application.title=dashconforme
|
||||
application.description=dashconforme
|
||||
application.fluig.version=null
|
||||
application.category=SYSTEM
|
||||
application.renderer=freemarker
|
||||
developer.code=andrey.cunha
|
||||
developer.name=andrey.cunha
|
||||
developer.url=http://www.fluig.com
|
||||
application.uiwidget=true
|
||||
application.mobileapp=false
|
||||
application.version=${build.version}-${build.revision}
|
||||
view.file=view.ftl
|
||||
edit.file=edit.ftl
|
||||
locale.file.base.name=dashconforme
|
||||
application.resource.js.1=/resources/js/dashconforme.js
|
||||
application.resource.css.2=/resources/css/dashconforme.css
|
||||
hash=4a16315e9e66fa7d797b3f6b1fb365b69f9a4ce2
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<div id="MyWidget_${instanceId}" class="super-widget wcm-widget-class fluig-style-guide" data-params="MyWidget.instance()">
|
||||
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
<div id="dashConforme_${instanceId}" class="super-widget wcm-widget-class fluig-style-guide" data-params="DashConforme.instance()">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Top Inconformidades</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<canvas id="graficoConforme_${instanceId}" height="120"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web>
|
||||
<context-root>/dashconforme</context-root>
|
||||
<disable-cross-context>false</disable-cross-context>
|
||||
</jboss-web>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
</web-app>
|
||||
@ -0,0 +1,3 @@
|
||||
div[id^="dashConforme_"] canvas {
|
||||
max-height: 420px;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
@ -0,0 +1,149 @@
|
||||
var DashConforme = SuperWidget.extend({
|
||||
|
||||
chart:null,
|
||||
|
||||
init:function(){
|
||||
|
||||
var self=this;
|
||||
this.renderAmostra();
|
||||
|
||||
window.addEventListener("dashboardData",function(e){
|
||||
|
||||
self.render(e.detail || []);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
render:function(dados){
|
||||
|
||||
var mapa = {};
|
||||
|
||||
dados.forEach(function(item){
|
||||
var lista = String(item.listaNaoConforme || "").trim();
|
||||
if(!lista){
|
||||
return;
|
||||
}
|
||||
|
||||
lista.split("|").forEach(function(indicador){
|
||||
var chave = String(indicador || "").trim();
|
||||
if(!chave){
|
||||
return;
|
||||
}
|
||||
if(!mapa[chave]){
|
||||
mapa[chave] = 0;
|
||||
}
|
||||
mapa[chave] += 1;
|
||||
});
|
||||
});
|
||||
|
||||
var pares = Object.keys(mapa).map(function(k){
|
||||
return {nome:k,valor:mapa[k]};
|
||||
});
|
||||
|
||||
pares.sort(function(a,b){
|
||||
return b.valor - a.valor;
|
||||
});
|
||||
|
||||
pares = pares.slice(0,10);
|
||||
|
||||
var labels = pares.map(function(p){ return p.nome; });
|
||||
var valores = pares.map(function(p){ return p.valor; });
|
||||
|
||||
if(!labels.length){
|
||||
labels = ["Aguardando filtro"];
|
||||
valores = [0];
|
||||
}
|
||||
|
||||
var ctx = document.getElementById("graficoConforme_"+this.instanceId);
|
||||
if(!ctx){
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.chart){
|
||||
this.chart.destroy();
|
||||
}
|
||||
|
||||
this.chart = new Chart(ctx,{
|
||||
type:"bar",
|
||||
data:{
|
||||
labels:labels,
|
||||
datasets:[{
|
||||
label:"Ocorrências",
|
||||
data:valores,
|
||||
backgroundColor:"#f39c12"
|
||||
}]
|
||||
},
|
||||
options:{
|
||||
responsive:true,
|
||||
maintainAspectRatio:false,
|
||||
indexAxis:"x",
|
||||
plugins:{
|
||||
legend:{display:false},
|
||||
tooltip:{
|
||||
callbacks:{
|
||||
title:function(items){
|
||||
if(labels.length === 1 && labels[0] === "Aguardando filtro"){
|
||||
return "Aguardando filtro";
|
||||
}
|
||||
return items && items.length ? labels[items[0].dataIndex] : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales:{
|
||||
x:{
|
||||
ticks:{
|
||||
autoSkip:false,
|
||||
maxRotation:35,
|
||||
minRotation:0,
|
||||
callback:function(value,index){
|
||||
var txt = labels[index] || "";
|
||||
return txt.length > 38 ? txt.substring(0,38) + "..." : txt;
|
||||
}
|
||||
}
|
||||
},
|
||||
y:{
|
||||
beginAtZero:true,
|
||||
precision:0
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
renderAmostra:function(){
|
||||
var ctx = document.getElementById("graficoConforme_"+this.instanceId);
|
||||
if(!ctx){
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.chart){
|
||||
this.chart.destroy();
|
||||
}
|
||||
|
||||
this.chart = new Chart(ctx,{
|
||||
type:"bar",
|
||||
data:{
|
||||
labels:["Aguardando filtro"],
|
||||
datasets:[{
|
||||
label:"Ocorrências",
|
||||
data:[0],
|
||||
backgroundColor:"#cfd8dc"
|
||||
}]
|
||||
},
|
||||
options:{
|
||||
responsive:true,
|
||||
maintainAspectRatio:false,
|
||||
plugins:{legend:{display:false}},
|
||||
scales:{
|
||||
x:{ticks:{autoSkip:false,maxRotation:0,minRotation:0}},
|
||||
y:{beginAtZero:true,precision:0}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
Binary file not shown.
@ -0,0 +1,19 @@
|
||||
application.type=widget
|
||||
application.code=dashdata
|
||||
application.title=dashdata
|
||||
application.description=dashdata
|
||||
application.fluig.version=null
|
||||
application.category=SYSTEM
|
||||
application.renderer=freemarker
|
||||
developer.code=andrey.cunha
|
||||
developer.name=andrey.cunha
|
||||
developer.url=http://www.fluig.com
|
||||
application.uiwidget=true
|
||||
application.mobileapp=false
|
||||
application.version=${build.version}-${build.revision}
|
||||
view.file=view.ftl
|
||||
edit.file=edit.ftl
|
||||
locale.file.base.name=dashdata
|
||||
application.resource.js.1=/resources/js/dashdata.js
|
||||
application.resource.css.2=/resources/css/dashdata.css
|
||||
hash=4a16315e9e66fa7d797b3f6b1fb365b69f9a4ce2
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<div id="MyWidget_${instanceId}" class="super-widget wcm-widget-class fluig-style-guide" data-params="MyWidget.instance()">
|
||||
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<div id="dashdata_${instanceId}"
|
||||
class="super-widget wcm-widget-class"
|
||||
data-params="DashData.instance()">
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web>
|
||||
<context-root>/dashdata</context-root>
|
||||
<disable-cross-context>false</disable-cross-context>
|
||||
</jboss-web>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
</web-app>
|
||||
@ -0,0 +1 @@
|
||||
/* Coloque aqui seu codigo CSS */
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
@ -0,0 +1,123 @@
|
||||
var DashData = SuperWidget.extend({
|
||||
|
||||
init:function(){
|
||||
|
||||
console.log("DashData carregado");
|
||||
|
||||
var self=this;
|
||||
|
||||
window.addEventListener("dashboardFiltro",function(e){
|
||||
|
||||
console.log("DashData recebeu filtros:",e.detail);
|
||||
|
||||
self.carregar(e.detail);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
carregar:function(filtros){
|
||||
|
||||
console.log("Consultando dataset...", filtros);
|
||||
|
||||
var self=this;
|
||||
|
||||
$.ajax({
|
||||
|
||||
url:"/api/public/ecm/dataset/search",
|
||||
type:"POST",
|
||||
contentType:"application/json",
|
||||
|
||||
data:JSON.stringify({
|
||||
datasetId:"ds_dashboard_checklist"
|
||||
}),
|
||||
|
||||
success:function(res){
|
||||
|
||||
console.log("Resposta dataset:",res);
|
||||
|
||||
var dados=res.content || [];
|
||||
|
||||
console.log("Quantidade registros:", dados.length);
|
||||
|
||||
// FILTRO POR LOJA
|
||||
if(filtros.loja){
|
||||
|
||||
dados = dados.filter(function(item){
|
||||
|
||||
return normalizaTexto(item.loja) === normalizaTexto(filtros.loja);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// FILTRO POR DATA
|
||||
if(filtros.dataInicio || filtros.dataFim){
|
||||
|
||||
dados = dados.filter(function(item){
|
||||
|
||||
var dataInicioAuditoria = normalizaData(item.dataAuditoria);
|
||||
var dataLimite = normalizaData(item.dataLimite);
|
||||
var inicioFiltro = normalizaData(filtros.dataInicio);
|
||||
var fimFiltro = normalizaData(filtros.dataFim);
|
||||
|
||||
// Mantem quando data de auditoria OU data limite estiver na faixa filtrada
|
||||
return dataNaFaixa(dataInicioAuditoria, inicioFiltro, fimFiltro) ||
|
||||
dataNaFaixa(dataLimite, inicioFiltro, fimFiltro);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Mantem somente auditorias com status final (evita divergencia entre total e KPIs)
|
||||
var antesStatus = dados.length;
|
||||
dados = dados.filter(function(item){
|
||||
var st = normalizaTexto(item.saidaAnalise || item.status || "");
|
||||
return st === "CONFORME" || st === "NAO_CONFORME";
|
||||
});
|
||||
console.log("Registros com status final:", dados.length, "de", antesStatus);
|
||||
|
||||
// Ordena por data de auditoria mais recente
|
||||
dados.sort(function(a,b){
|
||||
var da = normalizaData(a.dataAuditoria);
|
||||
var db = normalizaData(b.dataAuditoria);
|
||||
if(da < db) return 1;
|
||||
if(da > db) return -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
console.log("Registros filtrados:", dados);
|
||||
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("dashboardData",{detail:dados})
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function normalizaTexto(valor){
|
||||
return String(valor || "").trim().toUpperCase();
|
||||
}
|
||||
|
||||
function normalizaData(valor){
|
||||
var v = String(valor || "").trim();
|
||||
return v;
|
||||
}
|
||||
|
||||
function dataNaFaixa(data, inicio, fim){
|
||||
if(!data){
|
||||
return false;
|
||||
}
|
||||
if(inicio && data < inicio){
|
||||
return false;
|
||||
}
|
||||
if(fim && data > fim){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
BIN
Auditoria_checklist/wcm/widget/dashdata/target/dashdata.war
Normal file
BIN
Auditoria_checklist/wcm/widget/dashdata/target/dashdata.war
Normal file
Binary file not shown.
@ -0,0 +1,19 @@
|
||||
application.type=widget
|
||||
application.code=dashgrafico
|
||||
application.title=dashgrafico
|
||||
application.description=dashgrafico
|
||||
application.fluig.version=null
|
||||
application.category=SYSTEM
|
||||
application.renderer=freemarker
|
||||
developer.code=G-ALES1NT-TEC09
|
||||
developer.name=andrey.cunha
|
||||
developer.url=http://www.fluig.com
|
||||
application.uiwidget=true
|
||||
application.mobileapp=false
|
||||
application.version=${build.version}-${build.revision}
|
||||
view.file=view.ftl
|
||||
edit.file=edit.ftl
|
||||
locale.file.base.name=dashgrafico
|
||||
application.resource.js.1=/resources/js/dashgrafico.js
|
||||
application.resource.css.2=/resources/css/dashgrafico.css
|
||||
hash=4a16315e9e66fa7d797b3f6b1fb365b69f9a4ce2
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<div id="MyWidget_${instanceId}" class="super-widget wcm-widget-class fluig-style-guide" data-params="MyWidget.instance()">
|
||||
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
<div id="dashGrafico_${instanceId}"
|
||||
class="super-widget wcm-widget-class fluig-style-guide"
|
||||
data-params="DashGrafico.instance()">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
|
||||
<div style="height:260px; max-width:360px; margin:0 auto;">
|
||||
<canvas id="grafico_${instanceId}"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web>
|
||||
<context-root>/dashgrafico</context-root>
|
||||
<disable-cross-context>false</disable-cross-context>
|
||||
</jboss-web>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
</web-app>
|
||||
@ -0,0 +1 @@
|
||||
/* Coloque aqui seu codigo CSS */
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
@ -0,0 +1,91 @@
|
||||
var DashGrafico = SuperWidget.extend({
|
||||
|
||||
chart:null,
|
||||
|
||||
init:function(){
|
||||
|
||||
var self=this;
|
||||
this.renderAmostra();
|
||||
|
||||
window.addEventListener("dashboardData",function(e){
|
||||
|
||||
self.render(e.detail);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
render:function(dados){
|
||||
|
||||
var conforme=dados.filter(function(i){
|
||||
return normalizaStatus(i)=="CONFORME";
|
||||
}).length;
|
||||
|
||||
var nao=dados.filter(function(i){
|
||||
return normalizaStatus(i)=="NAO_CONFORME";
|
||||
}).length;
|
||||
|
||||
var ctx=document.getElementById("grafico_"+this.instanceId);
|
||||
|
||||
if(this.chart){
|
||||
this.chart.destroy();
|
||||
}
|
||||
|
||||
this.chart=new Chart(ctx,{
|
||||
|
||||
type:'doughnut',
|
||||
|
||||
data:{
|
||||
labels:["Conforme ("+conforme+")","Não Conforme ("+nao+")"],
|
||||
datasets:[{
|
||||
data:[conforme,nao],
|
||||
backgroundColor:["#2ecc71","#e74c3c"]
|
||||
}]
|
||||
},
|
||||
options:{
|
||||
responsive:true,
|
||||
maintainAspectRatio:false,
|
||||
cutout:"48%"
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function normalizaStatus(item){
|
||||
var raw = item.saidaAnalise || item.status || "";
|
||||
return String(raw).trim().toUpperCase();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
renderAmostra:function(){
|
||||
var ctx=document.getElementById("grafico_"+this.instanceId);
|
||||
if(!ctx){
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.chart){
|
||||
this.chart.destroy();
|
||||
}
|
||||
|
||||
this.chart=new Chart(ctx,{
|
||||
type:'doughnut',
|
||||
data:{
|
||||
labels:["Conforme (0)","Não Conforme (0)"],
|
||||
datasets:[{
|
||||
data:[1,0],
|
||||
backgroundColor:["#cfd8dc","#eceff1"]
|
||||
}]
|
||||
},
|
||||
options:{
|
||||
responsive:true,
|
||||
maintainAspectRatio:false,
|
||||
cutout:"48%",
|
||||
plugins:{
|
||||
tooltip:{enabled:false}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
Binary file not shown.
@ -0,0 +1,19 @@
|
||||
application.type=widget
|
||||
application.code=dashkpi
|
||||
application.title=dashkpi
|
||||
application.description=dashkpi
|
||||
application.fluig.version=null
|
||||
application.category=SYSTEM
|
||||
application.renderer=freemarker
|
||||
developer.code=andrey.cunha
|
||||
developer.name=andrey.cunha
|
||||
developer.url=http://www.fluig.com
|
||||
application.uiwidget=true
|
||||
application.mobileapp=false
|
||||
application.version=${build.version}-${build.revision}
|
||||
view.file=view.ftl
|
||||
edit.file=edit.ftl
|
||||
locale.file.base.name=dashkpi
|
||||
application.resource.js.1=/resources/js/dashkpi.js
|
||||
application.resource.css.2=/resources/css/dashkpi.css
|
||||
hash=4a16315e9e66fa7d797b3f6b1fb365b69f9a4ce2
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
<div id="MyWidget_${instanceId}" class="super-widget wcm-widget-class fluig-style-guide" data-params="MyWidget.instance()">
|
||||
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
<div id="dashKPI_${instanceId}"
|
||||
class="super-widget wcm-widget-class fluig-style-guide"
|
||||
data-params="DashKPI.instance()">
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h4>Total Auditorias</h4>
|
||||
<h2 id="kpi_total_${instanceId}">0</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-body">
|
||||
<h4>Conformes</h4>
|
||||
<h2 id="kpi_ok_${instanceId}">0</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-body">
|
||||
<h4>Não Conformes</h4>
|
||||
<h2 id="kpi_nok_${instanceId}">0</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-body">
|
||||
<h4>% Conformidade</h4>
|
||||
<h2 id="kpi_pct_${instanceId}">0%</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web>
|
||||
<context-root>/dashkpi</context-root>
|
||||
<disable-cross-context>false</disable-cross-context>
|
||||
</jboss-web>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
</web-app>
|
||||
@ -0,0 +1 @@
|
||||
/* Coloque aqui seu codigo CSS */
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
@ -0,0 +1,41 @@
|
||||
var DashKPI = SuperWidget.extend({
|
||||
|
||||
init:function(){
|
||||
|
||||
var self=this;
|
||||
|
||||
window.addEventListener("dashboardData",function(e){
|
||||
|
||||
self.calcular(e.detail);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
calcular:function(dados){
|
||||
|
||||
var total=dados.length;
|
||||
|
||||
var conformes=dados.filter(function(i){
|
||||
return normalizaStatus(i)=="CONFORME";
|
||||
}).length;
|
||||
|
||||
var nao=dados.filter(function(i){
|
||||
return normalizaStatus(i)=="NAO_CONFORME";
|
||||
}).length;
|
||||
|
||||
var pct= total ? Math.round((conformes/total)*100) : 0;
|
||||
|
||||
$("#kpi_total_"+this.instanceId).text(total);
|
||||
$("#kpi_ok_"+this.instanceId).text(conformes);
|
||||
$("#kpi_nok_"+this.instanceId).text(nao);
|
||||
$("#kpi_pct_"+this.instanceId).text(pct+"%");
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function normalizaStatus(item){
|
||||
var raw = item.saidaAnalise || item.status || "";
|
||||
return String(raw).trim().toUpperCase();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user