Plugin Directory

Changeset 3447337


Ignore:
Timestamp:
01/26/2026 07:44:54 PM (3 weeks ago)
Author:
zephyrwp
Message:

Setup Wizard

Location:
iris-ai/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • iris-ai/trunk/assets/css/admin.css

    r3424224 r3447337  
    443443    display: flex;
    444444    align-items: center;
    445     justify-content:flex-start;
     445    justify-content: flex-start;
    446446    gap: 15px;
    447447}
     
    911911    line-height: 1.6;
    912912}
     913
    913914/* ============================================================================
    914915   Margin Utilities
    915916   ============================================================================ */
    916  
     917
    917918.irisai-mb-20 {
    918919    margin-bottom: 20px;
     
    934935    margin-bottom: 15px;
    935936}
     937
    936938.irisai-textarea-full {
    937939    width: 100%;
     
    939941    box-sizing: border-box;
    940942}
     943
     944/* ============================= */
     945/* IrisAI Setup Wizard Styles    */
     946/* ============================= */
     947 
     948
     949.irisai-form-card {
     950    background: #fff;
     951    border: 2px solid #e2e8f0;
     952    border-radius: 12px;
     953    padding: 32px;
     954    margin-bottom: 24px;
     955    display: flex;
     956    gap: 20px;
     957    align-items: flex-start;
     958}
     959
     960.irisai-form-card .form-card-icon {
     961    width: 56px;
     962    height: 56px;
     963    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     964    border-radius: 12px;
     965    display: flex;
     966    align-items: center;
     967    justify-content: center;
     968    color: #fff;
     969    flex-shrink: 0;
     970}
     971
     972.irisai-form-card .form-card-icon.openai {
     973    background: linear-gradient(135deg, #10a37f 0%, #0d8a6a 100%);
     974}
     975
     976.irisai-form-card .form-card-content {
     977    flex: 1;
     978}
     979
     980.irisai-form-card .form-card-content label {
     981    display: block;
     982    font-size: 16px;
     983    margin-bottom: 12px;
     984    color: #1e293b;
     985}
     986
     987.irisai-api-input {
     988    width: 100%;
     989    padding: 12px 16px;
     990    font-size: 14px;
     991    border: 2px solid #e2e8f0;
     992    border-radius: 8px;
     993    transition: all 0.2s ease;
     994    font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
     995}
     996
     997.irisai-api-input:focus {
     998    border-color: #667eea;
     999    outline: none;
     1000    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
     1001}
     1002
     1003.irisai-wizard-inner-container .field-description {
     1004    margin: 12px 0 0;
     1005    font-size: 13px;
     1006    color: #64748b;
     1007    display: flex;
     1008    align-items: center;
     1009    gap: 6px;
     1010}
     1011
     1012.irisai-wizard-inner-container .field-description .dashicons {
     1013    font-size: 16px;
     1014    width: 16px;
     1015    height: 16px;
     1016}
     1017
     1018.irisai-wizard-inner-container .field-description a {
     1019    color: #667eea;
     1020    text-decoration: none;
     1021    font-weight: 500;
     1022    display: inline-flex;
     1023    align-items: center;
     1024    gap: 4px;
     1025}
     1026
     1027.irisai-wizard-inner-container .field-description a:hover {
     1028    text-decoration: underline;
     1029}
     1030
     1031.irisai-wizard-inner-container .field-description a .dashicons {
     1032    font-size: 14px;
     1033    width: 14px;
     1034    height: 14px;
     1035}
     1036
     1037.irisai-info-box {
     1038    background: #f0f9ff;
     1039    border: 1px solid #bae6fd;
     1040    border-radius: 8px;
     1041    padding: 20px;
     1042    display: flex;
     1043    gap: 16px;
     1044    margin-bottom: 32px;
     1045}
     1046
     1047.irisai-info-box.warning {
     1048    background: #fffbeb;
     1049    border-color: #fde68a;
     1050}
     1051
     1052.irisai-wizard-inner-container .info-box-icon {
     1053    width: 40px;
     1054    height: 40px;
     1055    background: #dbeafe;
     1056    border-radius: 8px;
     1057    display: flex;
     1058    align-items: center;
     1059    justify-content: center;
     1060    color: #0284c7;
     1061    flex-shrink: 0;
     1062}
     1063
     1064.irisai-info-box.warning .info-box-icon {
     1065    background: #fef3c7;
     1066    color: #d97706;
     1067}
     1068
     1069.irisai-wizard-inner-container .info-box-icon .dashicons {
     1070    font-size: 22px;
     1071    width: 22px;
     1072    height: 22px;
     1073}
     1074
     1075.irisai-wizard-inner-container .info-box-content {
     1076    flex: 1;
     1077}
     1078
     1079.irisai-wizard-inner-container .info-box-content strong {
     1080    display: block;
     1081    margin-bottom: 8px;
     1082    color: #1e293b;
     1083    font-size: 14px;
     1084}
     1085
     1086.irisai-wizard-inner-container .info-box-content ul {
     1087    margin: 0;
     1088    padding-left: 20px;
     1089}
     1090
     1091.irisai-wizard-inner-container .info-box-content ul li {
     1092    font-size: 13px;
     1093    color: #475569;
     1094    margin-bottom: 4px;
     1095    line-height: 1.5;
     1096}
     1097
     1098.irisai-wizard-inner-container .info-box-content ul li:last-child {
     1099    margin-bottom: 0;
     1100}
     1101
     1102.irisai-skip-form {
     1103    text-align: center;
     1104}
     1105
     1106.irisai-content-selection {
     1107    margin-bottom: 32px;
     1108}
     1109
     1110.irisai-content-selection .selection-header {
     1111    margin-bottom: 24px;
     1112}
     1113
     1114.irisai-content-selection .selection-header h3 {
     1115    font-size: 18px;
     1116    font-weight: 600;
     1117    margin: 0 0 8px;
     1118    color: #1e293b;
     1119}
     1120
     1121.irisai-content-selection .selection-header p {
     1122    font-size: 14px;
     1123    color: #64748b;
     1124    margin: 0;
     1125}
     1126
     1127.irisai-content-selection .content-types-grid {
     1128    display: grid;
     1129    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
     1130    gap: 16px;
     1131    margin-bottom: 24px;
     1132}
     1133
     1134.irisai-content-selection .content-type-card {
     1135    position: relative;
     1136    background: #fff;
     1137    border: 2px solid #e2e8f0;
     1138    border-radius: 10px;
     1139    padding: 20px;
     1140    cursor: pointer;
     1141    transition: all 0.2s ease;
     1142    display: flex;
     1143    align-items: center;
     1144    gap: 16px;
     1145}
     1146
     1147.irisai-content-selection .content-type-card input[type="checkbox"] {
     1148    position: absolute;
     1149    opacity: 0;
     1150    pointer-events: none;
     1151}
     1152
     1153.irisai-content-selection .content-type-card:hover {
     1154    border-color: #cbd5e1;
     1155    transform: translateY(-2px);
     1156    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
     1157}
     1158
     1159.irisai-content-selection .content-type-card.selected {
     1160    border-color: #667eea;
     1161    background: #f8f9ff;
     1162    box-shadow: 0 2px 8px rgba(102, 126, 234, 0.1);
     1163}
     1164
     1165.irisai-content-selection .card-icon {
     1166    width: 48px;
     1167    height: 48px;
     1168    background: #f1f5f9;
     1169    border-radius: 10px;
     1170    display: flex;
     1171    align-items: center;
     1172    justify-content: center;
     1173    flex-shrink: 0;
     1174    transition: all 0.2s ease;
     1175}
     1176
     1177.irisai-content-selection .content-type-card.selected .card-icon {
     1178    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1179    color: #fff;
     1180}
     1181
     1182.irisai-content-selection .card-icon .dashicons {
     1183    font-size: 24px;
     1184    width: 24px;
     1185    height: 24px;
     1186    color: #64748b;
     1187}
     1188
     1189.irisai-content-selection .content-type-card.selected .card-icon .dashicons {
     1190    color: #fff;
     1191}
     1192
     1193.irisai-content-selection .card-content {
     1194    flex: 1;
     1195}
     1196
     1197.irisai-content-selection .card-content h4 {
     1198    font-size: 15px;
     1199    font-weight: 600;
     1200    margin: 0 0 4px;
     1201    color: #1e293b;
     1202}
     1203
     1204.irisai-content-selection .post-count {
     1205    font-size: 13px;
     1206    color: #64748b;
     1207    margin: 0;
     1208}
     1209
     1210.irisai-content-selection .card-checkmark {
     1211    width: 24px;
     1212    height: 24px;
     1213    border-radius: 50%;
     1214    background: #e2e8f0;
     1215    display: flex;
     1216    align-items: center;
     1217    justify-content: center;
     1218    opacity: 0;
     1219    transition: all 0.2s ease;
     1220}
     1221
     1222.irisai-content-selection .content-type-card.selected .card-checkmark {
     1223    opacity: 1;
     1224    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1225}
     1226
     1227.irisai-content-selection .card-checkmark .dashicons {
     1228    color: #fff;
     1229    font-size: 16px;
     1230    width: 16px;
     1231    height: 16px;
     1232}
     1233
     1234
     1235
     1236.irisai-wizard-inner-container.finish-container {
     1237    text-align: center;
     1238}
     1239
     1240.irisai-wizard-inner-container .finish-celebration {
     1241    margin-bottom: 48px;
     1242}
     1243
     1244.irisai-wizard-inner-container .celebration-icon {
     1245    width: 120px;
     1246    height: 120px;
     1247    margin: 0 auto 32px;
     1248    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1249    border-radius: 50%;
     1250    display: flex;
     1251    align-items: center;
     1252    justify-content: center;
     1253    color: #fff;
     1254    animation: celebrate 0.6s ease-out;
     1255}
     1256
     1257@keyframes celebrate {
     1258    0% {
     1259        transform: scale(0);
     1260        opacity: 0;
     1261    }
     1262
     1263    50% {
     1264        transform: scale(1.1);
     1265    }
     1266
     1267    100% {
     1268        transform: scale(1);
     1269        opacity: 1;
     1270    }
     1271}
     1272
     1273.irisai-wizard-inner-container .finish-celebration h1 {
     1274    font-size: 36px;
     1275    font-weight: 700;
     1276    margin: 0 0 16px;
     1277    color: #1e293b;
     1278}
     1279
     1280.irisai-wizard-inner-container .celebration-subtitle {
     1281    font-size: 16px;
     1282    color: #64748b;
     1283    margin: 0 auto;
     1284    max-width: 600px;
     1285    line-height: 1.6;
     1286}
     1287
     1288.irisai-wizard-inner-container .finish-features {
     1289    display: grid;
     1290    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
     1291    gap: 24px;
     1292    margin-bottom: 48px;
     1293}
     1294
     1295.irisai-wizard-inner-container .feature-card {
     1296    background: #f8fafc;
     1297    border: 1px solid #e2e8f0;
     1298    border-radius: 12px;
     1299    padding: 32px 24px;
     1300    transition: all 0.2s ease;
     1301}
     1302
     1303.irisai-wizard-inner-container .feature-card:hover {
     1304    transform: translateY(-4px);
     1305    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
     1306    border-color: #cbd5e1;
     1307}
     1308
     1309.irisai-wizard-inner-container .feature-icon {
     1310    width: 56px;
     1311    height: 56px;
     1312    margin: 0 auto 20px;
     1313    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1314    border-radius: 14px;
     1315    display: flex;
     1316    align-items: center;
     1317    justify-content: center;
     1318    color: #fff;
     1319}
     1320
     1321.irisai-wizard-inner-container .feature-icon .dashicons {
     1322    font-size: 28px;
     1323    width: 28px;
     1324    height: 28px;
     1325}
     1326
     1327.irisai-wizard-inner-container .feature-card h3 {
     1328    font-size: 18px;
     1329    font-weight: 600;
     1330    margin: 0 0 12px;
     1331    color: #1e293b;
     1332}
     1333
     1334.irisai-wizard-inner-container .feature-card p {
     1335    font-size: 14px;
     1336    color: #64748b;
     1337    margin: 0;
     1338    line-height: 1.5;
     1339}
     1340
     1341.irisai-wizard-inner-container .finish-next-steps {
     1342    background: #f0f9ff;
     1343    border: 1px solid #bae6fd;
     1344    border-radius: 12px;
     1345    padding: 32px;
     1346    margin-bottom: 40px;
     1347    text-align: left;
     1348}
     1349
     1350.irisai-wizard-inner-container .finish-next-steps h3 {
     1351    font-size: 20px;
     1352    font-weight: 600;
     1353    margin: 0 0 20px;
     1354    color: #1e293b;
     1355    text-align: center;
     1356}
     1357
     1358.irisai-wizard-inner-container .finish-next-steps ul {
     1359    list-style: none;
     1360    margin: 0;
     1361    padding: 0;
     1362    max-width: 600px;
     1363    margin: 0 auto;
     1364}
     1365
     1366.irisai-wizard-inner-container .finish-next-steps li {
     1367    display: flex;
     1368    align-items: flex-start;
     1369    gap: 12px;
     1370    font-size: 15px;
     1371    color: #475569;
     1372    margin-bottom: 16px;
     1373    line-height: 1.6;
     1374}
     1375
     1376.irisai-wizard-inner-container .finish-next-steps li:last-child {
     1377    margin-bottom: 0;
     1378}
     1379
     1380.irisai-wizard-inner-container .finish-next-steps .dashicons {
     1381    color: #22c55e;
     1382    font-size: 24px;
     1383    width: 24px;
     1384    height: 24px;
     1385    flex-shrink: 0;
     1386    margin-top: -2px;
     1387}
     1388
     1389.irisai-wizard-inner-container .finish-actions {
     1390    display: flex;
     1391    gap: 16px;
     1392    justify-content: center;
     1393    flex-wrap: wrap;
     1394}
     1395
     1396.irisai-wizard-inner-container .finish-actions .button {
     1397    display: inline-flex;
     1398    align-items: center;
     1399    gap: 8px;
     1400}
     1401
     1402.irisai-wizard-inner-container .finish-actions .button .dashicons {
     1403    font-size: 18px;
     1404    width: 18px;
     1405    height: 18px;
     1406}
     1407
     1408.irisai-wizard-inner-container .finish-actions .button-hero {
     1409    font-size: 16px;
     1410    padding: 14px 32px;
     1411    height: auto;
     1412    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1413    border: none;
     1414    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
     1415}
     1416
     1417.irisai-wizard-inner-container .finish-actions .button-hero:hover {
     1418    background: linear-gradient(135deg, #5568d3 0%, #6a3f8f 100%);
     1419    transform: translateY(-2px);
     1420    box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
     1421}
     1422
     1423.irisai-wizard-inner-container .finish-actions .button-secondary {
     1424    font-size: 16px;
     1425    padding: 14px 32px;
     1426    height: auto;
     1427    border: 2px solid #e2e8f0;
     1428    background: #fff;
     1429}
     1430
     1431.irisai-wizard-inner-container .finish-actions .button-secondary:hover {
     1432    border-color: #cbd5e1;
     1433    background: #f8fafc;
     1434}
     1435
     1436.irisai-mode-options {
     1437    display: grid;
     1438    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
     1439    gap: 24px;
     1440    margin-bottom: 32px;
     1441}
     1442
     1443.irisai-mode-card {
     1444    position: relative;
     1445    background: #fff;
     1446    border: 2px solid #e2e8f0;
     1447    border-radius: 12px;
     1448    padding: 24px;
     1449    cursor: pointer;
     1450    transition: all 0.2s ease;
     1451    display: block;
     1452}
     1453
     1454.irisai-mode-card input[type="radio"] {
     1455    position: absolute;
     1456    opacity: 0;
     1457    pointer-events: none;
     1458}
     1459
     1460.irisai-mode-card:hover {
     1461    border-color: #cbd5e1;
     1462    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
     1463    transform: translateY(-2px);
     1464}
     1465
     1466.irisai-mode-card.selected {
     1467    border-color: #667eea;
     1468    background: #f8f9ff;
     1469    box-shadow: 0 4px 16px rgba(102, 126, 234, 0.15);
     1470}
     1471
     1472.irisai-mode-options .mode-card-content {
     1473    position: relative;
     1474}
     1475
     1476.irisai-mode-options .mode-icon {
     1477    width: 48px;
     1478    height: 48px;
     1479    background: #f1f5f9;
     1480    border-radius: 10px;
     1481    display: flex;
     1482    align-items: center;
     1483    justify-content: center;
     1484    margin-bottom: 16px;
     1485    color: #64748b;
     1486}
     1487
     1488.irisai-mode-options .mode-icon.recommended {
     1489    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1490    color: #fff;
     1491}
     1492
     1493.irisai-mode-options .mode-header {
     1494    display: flex;
     1495    align-items: center;
     1496    gap: 12px;
     1497    margin-bottom: 12px;
     1498}
     1499
     1500.irisai-mode-options .mode-header h3 {
     1501    font-size: 18px;
     1502    font-weight: 600;
     1503    margin: 0;
     1504    color: #1e293b;
     1505}
     1506
     1507.irisai-mode-options .badge {
     1508    font-size: 11px;
     1509    font-weight: 600;
     1510    text-transform: uppercase;
     1511    padding: 4px 10px;
     1512    border-radius: 12px;
     1513    letter-spacing: 0.5px;
     1514}
     1515
     1516.irisai-mode-options .badge.recommended {
     1517    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1518    color: #fff;
     1519}
     1520
     1521.irisai-mode-options .badge.basic {
     1522    background: #f1f5f9;
     1523    color: #64748b;
     1524}
     1525
     1526.irisai-mode-options .mode-description {
     1527    font-size: 14px;
     1528    line-height: 1.6;
     1529    color: #64748b;
     1530    margin: 0 0 16px;
     1531}
     1532
     1533.irisai-mode-options .mode-features {
     1534    list-style: none;
     1535    margin: 0;
     1536    padding: 0;
     1537}
     1538
     1539.irisai-mode-options .mode-features li {
     1540    display: flex;
     1541    align-items: center;
     1542    gap: 8px;
     1543    font-size: 13px;
     1544    color: #475569;
     1545    margin-bottom: 8px;
     1546}
     1547
     1548.irisai-mode-options .mode-features li:last-child {
     1549    margin-bottom: 0;
     1550}
     1551
     1552.irisai-mode-options .mode-features .dashicons {
     1553    width: 18px;
     1554    height: 18px;
     1555    font-size: 18px;
     1556}
     1557
     1558.irisai-mode-options .mode-features .dashicons-yes-alt {
     1559    color: #10b981;
     1560}
     1561
     1562.irisai-mode-options .mode-features .dashicons-minus {
     1563    color: #94a3b8;
     1564}
     1565
     1566.irisai-mode-options .mode-checkmark {
     1567    position: absolute;
     1568    top: 20px;
     1569    right: 20px;
     1570    width: 28px;
     1571    height: 28px;
     1572    border-radius: 50%;
     1573    background: #e2e8f0;
     1574    display: flex;
     1575    align-items: center;
     1576    justify-content: center;
     1577    opacity: 0;
     1578    transition: all 0.2s ease;
     1579}
     1580
     1581.irisai-mode-card.selected .mode-checkmark {
     1582    opacity: 1;
     1583    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1584}
     1585
     1586.irisai-mode-options .mode-checkmark .dashicons {
     1587    color: #fff;
     1588    font-size: 16px;
     1589    width: 16px;
     1590    height: 16px;
     1591}
     1592
     1593.irisai-status-card {
     1594    background: #fff;
     1595    border: 2px solid #e2e8f0;
     1596    border-radius: 12px;
     1597    padding: 24px;
     1598    display: flex;
     1599    gap: 20px;
     1600    align-items: flex-start;
     1601    margin-bottom: 32px;
     1602}
     1603
     1604.irisai-status-card.success {
     1605    background: #f0fdf4;
     1606    border-color: #86efac;
     1607}
     1608
     1609.irisai-status-card.warning {
     1610    background: #fffbeb;
     1611    border-color: #fde68a;
     1612}
     1613
     1614.irisai-wizard-inner-container .status-icon {
     1615    width: 48px;
     1616    height: 48px;
     1617    border-radius: 12px;
     1618    display: flex;
     1619    align-items: center;
     1620    justify-content: center;
     1621    flex-shrink: 0;
     1622}
     1623
     1624.irisai-status-card.success .status-icon {
     1625    background: #22c55e;
     1626    color: #fff;
     1627}
     1628
     1629.irisai-status-card.warning .status-icon {
     1630    background: #f59e0b;
     1631    color: #fff;
     1632}
     1633
     1634.irisai-wizard-inner-container .status-icon .dashicons {
     1635    font-size: 28px;
     1636    width: 28px;
     1637    height: 28px;
     1638}
     1639
     1640.irisai-wizard-inner-container .status-content h3 {
     1641    font-size: 16px;
     1642    font-weight: 600;
     1643    margin: 0 0 8px;
     1644    color: #1e293b;
     1645}
     1646
     1647.irisai-wizard-inner-container .status-content p {
     1648    font-size: 14px;
     1649    color: #64748b;
     1650    margin: 0;
     1651    line-height: 1.5;
     1652}
     1653
     1654.irisai-indexing-section {
     1655    background: #fff;
     1656    border: 2px solid #e2e8f0;
     1657    border-radius: 12px;
     1658    padding: 32px;
     1659    margin-bottom: 32px;
     1660}
     1661
     1662.irisai-wizard-inner-container .indexing-controls {
     1663    display: flex;
     1664    gap: 12px;
     1665    margin-bottom: 24px;
     1666}
     1667
     1668.irisai-wizard-inner-container .indexing-controls .button-hero {
     1669    display: inline-flex;
     1670    align-items: center;
     1671    height: auto;
     1672    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1673    border: none;
     1674    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
     1675    text-shadow: none;
     1676    display: inline-flex;
     1677    align-items: center;
     1678    gap: 8px;
     1679    font-size: 14px;
     1680    min-height: 46px;
     1681    line-height: 3.14285714;
     1682    padding: 0 36px;
     1683}
     1684
     1685.irisai-wizard-inner-container .indexing-controls .button-hero .dashicons {
     1686    font-size: 18px;
     1687    width: 18px;
     1688    height: 18px;
     1689}
     1690
     1691.irisai-wizard-inner-container .indexing-controls .button .dashicons {
     1692    font-size: 16px;
     1693    width: 16px;
     1694    height: 16px;
     1695    margin-right: 6px;
     1696}
     1697
     1698.irisai-wizard-inner-container .indexing-progress {
     1699    background: #f8fafc;
     1700    border: 1px solid #e2e8f0;
     1701    border-radius: 10px;
     1702    padding: 24px;
     1703    margin-top: 24px;
     1704}
     1705
     1706.irisai-wizard-inner-container .progress-header {
     1707    display: flex;
     1708    justify-content: space-between;
     1709    align-items: center;
     1710    margin-bottom: 12px;
     1711}
     1712
     1713.irisai-wizard-inner-container .progress-status {
     1714    display: flex;
     1715    align-items: center;
     1716    gap: 10px;
     1717    font-size: 14px;
     1718    font-weight: 600;
     1719    color: #1e293b;
     1720}
     1721
     1722.irisai-wizard-inner-container .status-dot {
     1723    width: 8px;
     1724    height: 8px;
     1725    border-radius: 50%;
     1726    background: #667eea;
     1727    animation: pulse 2s ease-in-out infinite;
     1728}
     1729
     1730@keyframes pulse {
     1731
     1732    0%,
     1733    100% {
     1734        opacity: 1;
     1735    }
     1736
     1737    50% {
     1738        opacity: 0.5;
     1739    }
     1740}
     1741
     1742.irisai-wizard-inner-container .progress-percentage {
     1743    font-size: 14px;
     1744    font-weight: 600;
     1745    color: #667eea;
     1746}
     1747
     1748.irisai-wizard-inner-container .progress-bar-container {
     1749    height: 12px;
     1750    background: #e2e8f0;
     1751    border-radius: 999px;
     1752    overflow: hidden;
     1753    margin-bottom: 12px;
     1754}
     1755
     1756.irisai-wizard-inner-container .progress-bar {
     1757    height: 100%;
     1758    width: 0%;
     1759    background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
     1760    transition: width 0.3s ease;
     1761    border-radius: 999px;
     1762}
     1763
     1764.irisai-wizard-inner-container .progress-details {
     1765    font-size: 13px;
     1766    color: #64748b;
     1767    margin: 0;
     1768}
     1769
     1770.irisai-wizard-inner-container .indexing-message {
     1771    margin-top: 20px;
     1772}
     1773
     1774.irisai-wizard-inner-container .indexing-message .notice {
     1775    margin: 0;
     1776    border-radius: 8px;
     1777}
     1778
     1779.irisai-wizard-inner-container .finish-form {
     1780    background: #f0fdf4;
     1781    border: 2px solid #86efac;
     1782    border-radius: 12px;
     1783    padding: 32px;
     1784    text-align: center;
     1785}
     1786
     1787.irisai-wizard-inner-container .finish-content {
     1788    display: flex;
     1789    align-items: center;
     1790    justify-content: center;
     1791    gap: 20px;
     1792    margin-bottom: 24px;
     1793}
     1794
     1795.irisai-wizard-inner-container .finish-icon {
     1796    width: 64px;
     1797    height: 64px;
     1798    background: #22c55e;
     1799    border-radius: 50%;
     1800    display: flex;
     1801    align-items: center;
     1802    justify-content: center;
     1803    color: #fff;
     1804}
     1805
     1806.irisai-wizard-inner-container .finish-icon .dashicons {
     1807    font-size: 36px;
     1808    width: 36px;
     1809    height: 36px;
     1810}
     1811
     1812.irisai-wizard-inner-container .finish-text {
     1813    text-align: left;
     1814}
     1815
     1816.irisai-wizard-inner-container .finish-text h3 {
     1817    font-size: 20px;
     1818    font-weight: 600;
     1819    margin: 0 0 6px;
     1820    color: #1e293b;
     1821}
     1822
     1823.irisai-wizard-inner-container .finish-text p {
     1824    font-size: 14px;
     1825    color: #64748b;
     1826    margin: 0;
     1827}
     1828
     1829.irisai-wizard-inner-container .finish-form .button-hero {
     1830    display: inline-flex;
     1831    align-items: center;
     1832    gap: 8px;
     1833}
     1834
     1835.irisai-wizard-container {
     1836    max-width: 900px;
     1837    margin: 40px auto;
     1838    background: #fff;
     1839    border-radius: 12px;
     1840    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
     1841    padding: 48px;
     1842}
     1843
     1844.irisai-wizard-header {
     1845    text-align: center;
     1846    margin-bottom: 48px;
     1847}
     1848
     1849.irisai-wizard-icon {
     1850    width: 72px;
     1851    height: 72px;
     1852    margin: 0 auto 24px;
     1853    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1854    border-radius: 16px;
     1855    display: flex;
     1856    align-items: center;
     1857    justify-content: center;
     1858    color: #fff;
     1859}
     1860
     1861.irisai-wizard-header h1 {
     1862    font-size: 32px;
     1863    font-weight: 600;
     1864    margin: 0 0 12px;
     1865    color: #1e293b;
     1866}
     1867
     1868.irisai-wizard-subtitle {
     1869    font-size: 16px;
     1870    color: #64748b;
     1871    margin: 0;
     1872}
     1873
     1874.irisai-wizard-steps-preview {
     1875    display: grid;
     1876    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
     1877    gap: 20px;
     1878    margin-bottom: 40px;
     1879}
     1880
     1881.irisai-step-card {
     1882    background: #f8fafc;
     1883    border: 1px solid #e2e8f0;
     1884    border-radius: 8px;
     1885    padding: 24px;
     1886    text-align: center;
     1887    transition: all 0.2s ease;
     1888}
     1889
     1890.irisai-step-card:hover {
     1891    border-color: #667eea;
     1892    transform: translateY(-2px);
     1893    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.1);
     1894}
     1895
     1896.irisai-wizard-inner-container .step-number {
     1897    width: 40px;
     1898    height: 40px;
     1899    margin: 0 auto 16px;
     1900    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1901    color: #fff;
     1902    border-radius: 50%;
     1903    display: flex;
     1904    align-items: center;
     1905    justify-content: center;
     1906    font-weight: 600;
     1907    font-size: 18px;
     1908}
     1909
     1910.irisai-wizard-inner-container .irisai-step-card h3 {
     1911    font-size: 16px;
     1912    font-weight: 600;
     1913    margin: 0 0 8px;
     1914    color: #1e293b;
     1915}
     1916
     1917.irisai-step-card p {
     1918    font-size: 13px;
     1919    color: #64748b;
     1920    margin: 0;
     1921    line-height: 1.5;
     1922}
     1923
     1924
     1925.irisai-wizard-actions .button-hero {
     1926    font-size: 16px;
     1927    padding: 12px 32px;
     1928    height: auto;
     1929    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     1930    border: none;
     1931    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
     1932    text-shadow: none;
     1933    display: inline-flex;
     1934    align-items: center;
     1935}
     1936
     1937.irisai-wizard-actions .button-hero:hover {
     1938    background: linear-gradient(135deg, #5568d3 0%, #6a3f8f 100%);
     1939    transform: translateY(-1px);
     1940    box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
     1941}
     1942
     1943
     1944.irisai-wizard-actions .button-link:hover {
     1945    color: #1e293b;
     1946}
     1947
     1948
     1949.irisai-setup-wrap {
     1950    margin: 20px 20px 0 0;
     1951}
     1952
     1953.irisai-wizard-notice-wrapper {
     1954    max-width: 900px;
     1955    margin: 20px auto 0;
     1956}
     1957
     1958.irisai-wizard-notice-wrapper .notice {
     1959    margin: 0 0 20px;
     1960    border-radius: 8px;
     1961    border-left-width: 4px;
     1962}
     1963
     1964.irisai-wizard-container {
     1965    max-width: 900px;
     1966    margin: 40px auto;
     1967    background: #fff;
     1968    border-radius: 12px;
     1969    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
     1970    padding: 48px;
     1971}
     1972
     1973.irisai-wizard-header {
     1974    text-align: center;
     1975    margin-bottom: 40px;
     1976}
     1977
     1978.irisai-wizard-header h1 {
     1979    font-size: 28px;
     1980    font-weight: 600;
     1981    margin: 0 0 12px;
     1982    color: #1e293b;
     1983}
     1984
     1985.irisai-wizard-subtitle {
     1986    font-size: 15px;
     1987    color: #64748b;
     1988    margin: 0;
     1989    line-height: 1.5;
     1990}
     1991
     1992.irisai-wizard-actions {
     1993    text-align: center;
     1994    margin-top: 32px;
     1995    padding-top: 24px;
     1996    border-top: 1px solid #e2e8f0;
     1997    display: flex;
     1998    flex-direction: column;
     1999    align-items:center;
     2000    gap: 5px;
     2001}
     2002
     2003
     2004.irisai-wizard-actions .button-hero {
     2005    font-size: 16px;
     2006    padding: 12px 32px;
     2007    height: auto;
     2008    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     2009    border: none;
     2010    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
     2011    text-shadow: none;
     2012    display: inline-flex;
     2013    align-items: center;
     2014    gap: 8px;
     2015}
     2016
     2017.irisai-wizard-actions .button-hero:hover {
     2018    background: linear-gradient(135deg, #5568d3 0%, #6a3f8f 100%);
     2019    transform: translateY(-1px);
     2020    box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
     2021}
     2022
     2023.irisai-wizard-actions .button-hero .dashicons {
     2024    margin: 0;
     2025    font-size: 18px;
     2026    width: 18px;
     2027    height: 18px;
     2028}
     2029
     2030.irisai-wizard-actions .button-link,.irisai-skip-form .button-link,.indexing-controls .button-link {
     2031    margin-top: 16px;
     2032    color: #64748b;
     2033    text-decoration: none;
     2034    padding: 5px 20px;
     2035    border-radius: 5px;
     2036    background: #f6f7f7;
     2037}
     2038.indexing-controls .button-link {
     2039    margin-top: 0;
     2040    display: flex;
     2041    align-items: center;
     2042}
     2043.irisai-wizard-actions .button-link:hover , .irisai-skip-form .button-link:hover, .indexing-controls .button-link:hover {
     2044    color: #1e293b;
     2045}
     2046
     2047.irisai-progress-bar-wrapper {
     2048    margin: 20px 0 24px;
     2049    padding: 0 20px;
     2050}
     2051
     2052.irisai-progress-info {
     2053    display: flex;
     2054    justify-content: space-between;
     2055    align-items: center;
     2056    margin-bottom: 8px;
     2057}
     2058
     2059.irisai-progress-step {
     2060    font-size: 13px;
     2061    font-weight: 600;
     2062    color: #1e293b;
     2063}
     2064
     2065.irisai-progress-percent {
     2066    font-size: 13px;
     2067    font-weight: 600;
     2068    color: #667eea;
     2069}
     2070
     2071.irisai-progress-bar-container {
     2072    height: 8px;
     2073    background: #e5e7eb;
     2074    border-radius: 999px;
     2075    overflow: hidden;
     2076    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05);
     2077}
     2078
     2079.irisai-progress-bar-fill {
     2080    height: 100%;
     2081    background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
     2082    border-radius: 999px;
     2083    transition: width 0.3s ease;
     2084    box-shadow: 0 1px 3px rgba(102, 126, 234, 0.3);
     2085}
     2086
     2087@media (max-width: 768px) {
     2088    .irisai-wizard-container {
     2089        padding: 32px 24px;
     2090        margin: 20px;
     2091    }
     2092
     2093    .irisai-wizard-header h1 {
     2094        font-size: 24px;
     2095    }
     2096}
     2097/* Shortcode Reference Section */
     2098.irisai-wizard-shortcode-ref {
     2099    background: #f8fafc;
     2100    border: 2px solid #e2e8f0;
     2101    border-radius: 12px;
     2102    padding: 32px;
     2103    margin-bottom: 32px;
     2104}
     2105
     2106.irisai-wizard-shortcode-ref h3 {
     2107    font-size: 18px;
     2108    font-weight: 600;
     2109    margin: 0 0 12px;
     2110    color: #1e293b;
     2111}
     2112
     2113.irisai-wizard-shortcode-ref > p {
     2114    font-size: 14px;
     2115    color: #64748b;
     2116    margin: 0 0 24px;
     2117    line-height: 1.6;
     2118}
     2119
     2120.irisai-wizard-shortcode-ref h4 {
     2121    font-size: 15px;
     2122    font-weight: 600;
     2123    margin: 0 0 12px;
     2124    color: #1e293b;
     2125}
     2126
     2127.irisai-wizard-shortcode-ref ul {
     2128    list-style: none;
     2129    margin: 0 0 24px;
     2130    padding: 0;
     2131}
     2132
     2133.irisai-wizard-shortcode-ref ul:last-child {
     2134    margin-bottom: 0;
     2135}
     2136
     2137.irisai-wizard-shortcode-ref li {
     2138    display: flex;
     2139    align-items: center;
     2140    gap: 12px;
     2141    font-size: 14px;
     2142    color: #475569;
     2143    margin-bottom: 12px;
     2144    padding: 12px;
     2145    background: #fff;
     2146    border: 1px solid #e2e8f0;
     2147    border-radius: 8px;
     2148    transition: all 0.2s ease;
     2149}
     2150
     2151.irisai-wizard-shortcode-ref li:last-child {
     2152    margin-bottom: 0;
     2153}
     2154
     2155.irisai-wizard-shortcode-ref li:hover {
     2156    border-color: #cbd5e1;
     2157    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
     2158}
     2159
     2160.irisai-wizard-shortcode-ref code {
     2161    font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
     2162    font-size: 13px;
     2163    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
     2164    color: #fff;
     2165    padding: 6px 12px;
     2166    border-radius: 6px;
     2167    font-weight: 500;
     2168    white-space: nowrap;
     2169    flex-shrink: 0;
     2170}
     2171
     2172.irisai-wizard-shortcode-ref .shortcode-description {
     2173    flex: 1;
     2174}
     2175
     2176.irisai-wizard-shortcode-ref .copy-shortcode {
     2177    display: inline-flex;
     2178    align-items: center;
     2179    gap: 6px;
     2180    padding: 8px 14px;
     2181    font-size: 13px;
     2182    height: auto;
     2183    min-height: 0;
     2184    line-height: 1;
     2185    flex-shrink: 0;
     2186}
     2187
     2188.irisai-wizard-shortcode-ref .copy-shortcode .dashicons {
     2189    font-size: 16px;
     2190    width: 16px;
     2191    height: 16px;
     2192}
  • iris-ai/trunk/includes/class-irisai-admin.php

    r3424224 r3447337  
    7070    {
    7171
    72         $allowed = array('post.php', 'post-new.php', 'toplevel_page_irisai');
    73 
    74         if (! in_array($hook, $allowed, true)) {
     72        if (
     73            strpos($hook, 'irisai') === false &&
     74            ! in_array($hook, ['post.php', 'post-new.php'], true)
     75        ) {
    7576            return;
    7677        }
     78
    7779
    7880        $base_path = IRISAI_PATH . 'assets/js/';
     
    101103            'vector-index'    => 'admin-vector-index.js',
    102104            'usage-guide'     => 'admin-usage-guide.js',
     105            'setup-wizard'     => 'admin-wizard.js',
    103106        );
    104107
  • iris-ai/trunk/includes/class-irisai-rest.php

    r3424224 r3447337  
    485485    public static function start_indexing($request)
    486486    {
     487
     488        if (! self::check_admin_permissions($request)) {
     489            return new \WP_Error('rest_forbidden', 'Unauthorized', ['status' => 401]);
     490        }
     491        return self::run_indexing();
     492    }
     493
     494    /**
     495     * Run indexing process (internal engine)
     496     *
     497     * This method contains the core indexing logic and is safe to be called
     498     * internally by the plugin (e.g., from the Setup Wizard) without requiring
     499     * REST authentication context.
     500     *
     501     * @since 1.1.0
     502     * @return WP_REST_Response Response object.
     503     */
     504    public static function run_indexing()
     505    {
     506       
     507        delete_transient('irisai_has_index');
    487508        $site_id = self::get_site_id();
    488509
     
    575596        $state['error'] = 'cancelled';
    576597        update_option("irisai_index_job_$job_id", $state, false);
     598        delete_transient('irisai_has_index');
    577599
    578600        return new WP_REST_Response(array('ok' => true), 200);
     
    689711            error_log('[IrisAI Worker] All posts processed! Marking job as complete');
    690712            $state['done'] = true;
     713            $state['completed_at'] = time();
     714            delete_transient('irisai_has_index');
    691715        }
    692716
     
    830854            } catch (\Exception $e) {
    831855                error_log('[IrisAI Worker] Error storing chunks for post ' . $post->ID . ': ' . $e->getMessage());
     856
     857
     858                /**
     859                 * @since 2.0.0
     860                 * On embedding/storage failure, mark the entire indexing job as failed
     861                 * and stop further processing.
     862                 */
     863                //  CRITICAL: mark job as failed
     864                $state['error'] = $e->getMessage();
     865                $state['error_details'] = sprintf(
     866                    'Post %d: %s',
     867                    $post->ID,
     868                    $e->getMessage()
     869                );
     870                $state['done'] = true;
     871
     872                update_option("irisai_index_job_$job_id", $state, false);
     873
     874                // Stop further processing
     875                return;
    832876            }
    833877        } else {
     
    10191063            // Clear dimension mismatch warning after successful full reindex
    10201064            delete_transient('irisai_embedding_mismatch_detected');
    1021 
     1065            delete_transient('irisai_has_index');
    10221066            return true;
    10231067        } else {
     
    11371181
    11381182            $deleted = IrisAI_Vector_DB::clear_site_data($site_id);
    1139 
     1183            delete_transient('irisai_has_index');
    11401184            // Clear any local indexing job states
    11411185            global $wpdb;
  • iris-ai/trunk/includes/settings/traits/trait-settings-widgetfields.php

    r3424224 r3447337  
    11<?php
     2
    23/**
    34 * Widget Settings Fields Trait
     
    1112namespace IrisAI;
    1213
    13 if ( ! defined( 'ABSPATH' ) ) {
     14if (! defined('ABSPATH')) {
    1415    exit;
    1516}
     
    2021 * Provides widget-related settings fields and sections.
    2122 */
    22 trait Settings_WidgetFields {
     23trait Settings_WidgetFields
     24{
    2325
    2426    /**
     
    2830     * @return void
    2931     */
    30     private static function register_widget_settings() {
     32    private static function register_widget_settings()
     33    {
    3134        // Auto-inject widget
    3235        register_setting(
     
    4649            array(
    4750                'type'              => 'string',
    48                 'sanitize_callback' => array( __CLASS__, 'sanitize_widget_position' ),
     51                'sanitize_callback' => array(__CLASS__, 'sanitize_widget_position'),
    4952                'default'           => 'bottom-right',
    5053            )
     
    5861                'type'              => 'string',
    5962                'sanitize_callback' => 'wp_kses_post',
    60                 'default'           => __( 'Hi! How can I help you today?', 'iris-ai' ),
     63                'default'           => __('Hi! How can I help you today?', 'iris-ai'),
    6164            )
    6265        );
     
    7982            array(
    8083                'type'              => 'integer',
    81                 'sanitize_callback' => array( __CLASS__, 'sanitize_max_history' ),
     84                'sanitize_callback' => array(__CLASS__, 'sanitize_max_history'),
    8285                'default'           => 50,
    8386            )
     
    113116                'type'              => 'string',
    114117                'sanitize_callback' => 'sanitize_text_field',
    115                 'default'           => __( 'Chat with us', 'iris-ai' ),
     118                'default'           => __('Chat with us', 'iris-ai'),
    116119            )
    117120        );
     
    135138     * @return void
    136139     */
    137     private static function add_widget_sections() {
     140    private static function add_widget_sections()
     141    {
    138142        add_settings_section(
    139143            'irisai_widget_section',
    140             __( 'Widget Configuration', 'iris-ai' ),
    141             array( __CLASS__, 'render_widget_section' ),
     144            __('Widget Configuration', 'iris-ai'),
     145            array(__CLASS__, 'render_widget_section'),
    142146            'irisai'
    143147        );
     
    145149        add_settings_section(
    146150            'irisai_widget_behavior_section',
    147             __( 'Widget Behavior', 'iris-ai' ),
    148             array( __CLASS__, 'render_widget_behavior_section' ),
     151            __('Widget Behavior', 'iris-ai'),
     152            array(__CLASS__, 'render_widget_behavior_section'),
    149153            'irisai'
    150154        );
     
    157161     * @return void
    158162     */
    159     private static function add_widget_fields() {
     163    private static function add_widget_fields()
     164    {
    160165        // Auto-inject widget
    161166        add_settings_field(
    162167            'irisai_auto_inject_widget',
    163             __( 'Auto-inject Widget', 'iris-ai' ),
    164             array( __CLASS__, 'field_auto_inject_widget' ),
     168            __('Auto-inject Widget', 'iris-ai'),
     169            array(__CLASS__, 'field_auto_inject_widget'),
    165170            'irisai',
    166171            'irisai_widget_section'
     
    170175        add_settings_field(
    171176            'irisai_widget_position',
    172             __( 'Widget Position', 'iris-ai' ),
    173             array( __CLASS__, 'field_widget_position' ),
     177            __('Widget Position', 'iris-ai'),
     178            array(__CLASS__, 'field_widget_position'),
    174179            'irisai',
    175180            'irisai_widget_section'
     
    179184        add_settings_field(
    180185            'irisai_widget_label',
    181             __( 'Widget Button Label', 'iris-ai' ),
    182             array( __CLASS__, 'field_widget_label' ),
     186            __('Widget Button Label', 'iris-ai'),
     187            array(__CLASS__, 'field_widget_label'),
    183188            'irisai',
    184189            'irisai_widget_section'
     
    188193        add_settings_field(
    189194            'irisai_welcome_message',
    190             __( 'Welcome Message', 'iris-ai' ),
    191             array( __CLASS__, 'field_welcome_message' ),
     195            __('Welcome Message', 'iris-ai'),
     196            array(__CLASS__, 'field_welcome_message'),
    192197            'irisai',
    193198            'irisai_widget_behavior_section'
     
    197202        add_settings_field(
    198203            'irisai_show_welcome',
    199             __( 'Show Welcome Message', 'iris-ai' ),
    200             array( __CLASS__, 'field_show_welcome' ),
     204            __('Show Welcome Message', 'iris-ai'),
     205            array(__CLASS__, 'field_show_welcome'),
    201206            'irisai',
    202207            'irisai_widget_behavior_section'
     
    206211        add_settings_field(
    207212            'irisai_show_suggestions_widget',
    208             __( 'Show Suggestion Chips', 'iris-ai' ),
    209             array( __CLASS__, 'field_show_suggestions_widget' ),
     213            __('Show Suggestion Chips', 'iris-ai'),
     214            array(__CLASS__, 'field_show_suggestions_widget'),
    210215            'irisai',
    211216            'irisai_widget_behavior_section'
     
    215220        add_settings_field(
    216221            'irisai_enable_history',
    217             __( 'Enable Chat History', 'iris-ai' ),
    218             array( __CLASS__, 'field_enable_history' ),
     222            __('Enable Chat History', 'iris-ai'),
     223            array(__CLASS__, 'field_enable_history'),
    219224            'irisai',
    220225            'irisai_widget_behavior_section'
     
    224229        add_settings_field(
    225230            'irisai_max_history',
    226             __( 'Max History Messages', 'iris-ai' ),
    227             array( __CLASS__, 'field_max_history' ),
     231            __('Max History Messages', 'iris-ai'),
     232            array(__CLASS__, 'field_max_history'),
    228233            'irisai',
    229234            'irisai_widget_behavior_section'
     
    233238        add_settings_field(
    234239            'irisai_enable_sources',
    235             __( 'Show Sources', 'iris-ai' ),
    236             array( __CLASS__, 'field_enable_sources' ),
     240            __('Show Sources', 'iris-ai'),
     241            array(__CLASS__, 'field_enable_sources'),
    237242            'irisai',
    238243            'irisai_widget_behavior_section'
     
    246251     * @return void
    247252     */
    248     public static function render_widget_section() {
    249         ?>
    250         <p><?php esc_html_e( 'Configure the floating chat widget that appears on your website. You can place it manually using the [irisai_widget] shortcode or enable auto-injection to show it on all pages.', 'iris-ai' ); ?></p>
     253    public static function render_widget_section()
     254    {
     255?>
     256        <p><?php esc_html_e('Configure the floating chat widget that appears on your website. You can place it manually using the [irisai_widget] shortcode or enable auto-injection to show it on all pages.', 'iris-ai'); ?></p>
    251257        <div class="notice notice-info inline">
    252258            <p>
    253                 <strong><?php esc_html_e( 'Shortcode Usage:', 'iris-ai' ); ?></strong>
    254                 <code>[irisai_widget]</code> - <?php esc_html_e( 'Default position', 'iris-ai' ); ?><br>
    255                 <code>[irisai_widget position="bottom-left"]</code> - <?php esc_html_e( 'Custom position', 'iris-ai' ); ?>
     259                <strong><?php esc_html_e('Shortcode Usage:', 'iris-ai'); ?></strong>
     260                <code>[irisai_widget]</code> - <?php esc_html_e('Default position', 'iris-ai'); ?><br>
     261                <code>[irisai_widget position="bottom-left"]</code> - <?php esc_html_e('Custom position', 'iris-ai'); ?>
    256262            </p>
    257263        </div>
    258         <?php
     264    <?php
    259265    }
    260266
     
    265271     * @return void
    266272     */
    267     public static function render_widget_behavior_section() {
    268         ?>
    269         <p><?php esc_html_e( 'Customize how the widget behaves and what information it displays to users.', 'iris-ai' ); ?></p>
    270         <?php
     273    public static function render_widget_behavior_section()
     274    {
     275    ?>
     276        <p><?php esc_html_e('Customize how the widget behaves and what information it displays to users.', 'iris-ai'); ?></p>
     277    <?php
    271278    }
    272279
     
    277284     * @return void
    278285     */
    279     public static function field_auto_inject_widget() {
    280         $value = get_option( 'irisai_auto_inject_widget', false );
    281         ?>
     286    public static function field_auto_inject_widget()
     287    {
     288        $value = get_option('irisai_auto_inject_widget', false);
     289    ?>
    282290        <label>
    283             <input 
    284                 type="checkbox" 
    285                 name="irisai_auto_inject_widget" 
    286                 value="1" 
    287                 <?php checked( $value, true ); ?> />
    288             <?php esc_html_e( 'Automatically add the chat widget to all pages', 'iris-ai' ); ?>
     291            <input
     292                type="checkbox"
     293                name="irisai_auto_inject_widget"
     294                value="1"
     295                <?php checked($value, true); ?> />
     296            <?php esc_html_e('Automatically add the chat widget to all pages', 'iris-ai'); ?>
    289297        </label>
    290298        <p class="description">
    291             <?php esc_html_e( 'When enabled, the widget will appear on all pages. When disabled, use the shortcode to place it manually.', 'iris-ai' ); ?>
    292         </p>
    293         <?php
     299            <?php esc_html_e('When enabled, the widget will appear on all pages. When disabled, use the shortcode to place it manually.', 'iris-ai'); ?>
     300        </p>
     301    <?php
    294302    }
    295303
     
    300308     * @return void
    301309     */
    302     public static function field_widget_position() {
    303         $value = get_option( 'irisai_widget_position', 'bottom-right' );
     310    public static function field_widget_position()
     311    {
     312        $value = get_option('irisai_widget_position', 'bottom-right');
    304313        $positions = array(
    305             'bottom-right' => __( 'Bottom Right', 'iris-ai' ),
    306             'bottom-left'  => __( 'Bottom Left', 'iris-ai' ),
    307             'top-right'    => __( 'Top Right', 'iris-ai' ),
    308             'top-left'     => __( 'Top Left', 'iris-ai' ),
    309         );
    310         ?>
     314            'bottom-right' => __('Bottom Right', 'iris-ai'),
     315            'bottom-left'  => __('Bottom Left', 'iris-ai'),
     316            'top-right'    => __('Top Right', 'iris-ai'),
     317            'top-left'     => __('Top Left', 'iris-ai'),
     318        );
     319    ?>
    311320        <select name="irisai_widget_position" id="irisai_widget_position">
    312             <?php foreach ( $positions as $key => $label ) : ?>
    313                 <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $value, $key ); ?>>
    314                     <?php echo esc_html( $label ); ?>
     321            <?php foreach ($positions as $key => $label) : ?>
     322                <option value="<?php echo esc_attr($key); ?>" <?php selected($value, $key); ?>>
     323                    <?php echo esc_html($label); ?>
    315324                </option>
    316325            <?php endforeach; ?>
    317326        </select>
    318327        <p class="description">
    319             <?php esc_html_e( 'Choose where the chat widget button appears on the screen.', 'iris-ai' ); ?>
    320         </p>
    321         <?php
     328            <?php esc_html_e('Choose where the chat widget button appears on the screen.', 'iris-ai'); ?>
     329        </p>
     330    <?php
    322331    }
    323332
     
    328337     * @return void
    329338     */
    330     public static function field_widget_label() {
    331         $value = get_option( 'irisai_widget_label', __( 'Chat with us', 'iris-ai' ) );
    332         ?>
    333         <input
    334             type="text"
    335             name="irisai_widget_label"
     339    public static function field_widget_label()
     340    {
     341        $value = get_option('irisai_widget_label', __('Chat with us', 'iris-ai'));
     342    ?>
     343        <input
     344            type="text"
     345            name="irisai_widget_label"
    336346            id="irisai_widget_label"
    337             value="<?php echo esc_attr( $value ); ?>"
     347            value="<?php echo esc_attr($value); ?>"
    338348            class="regular-text" />
    339349        <p class="description">
    340             <?php esc_html_e( 'The accessible label for the widget button (used for screen readers and tooltips).', 'iris-ai' ); ?>
    341         </p>
    342         <?php
     350            <?php esc_html_e('The accessible label for the widget button (used for screen readers and tooltips).', 'iris-ai'); ?>
     351        </p>
     352    <?php
    343353    }
    344354
     
    349359     * @return void
    350360     */
    351     public static function field_welcome_message() {
    352         $value = get_option( 'irisai_welcome_message', __( 'Hi! How can I help you today?', 'iris-ai' ) );
    353         ?>
    354         <textarea
    355             name="irisai_welcome_message"
     361    public static function field_welcome_message()
     362    {
     363        $value = get_option('irisai_welcome_message', __('Hi! How can I help you today?', 'iris-ai'));
     364    ?>
     365        <textarea
     366            name="irisai_welcome_message"
    356367            id="irisai_welcome_message"
    357             rows="3" 
    358             class="large-text"><?php echo esc_textarea( $value ); ?></textarea>
    359         <p class="description">
    360             <?php esc_html_e( 'The welcome message shown when users first open the chat widget. HTML is allowed.', 'iris-ai' ); ?>
    361         </p>
    362         <?php
     368            rows="3"
     369            class="large-text"><?php echo esc_textarea($value); ?></textarea>
     370        <p class="description">
     371            <?php esc_html_e('The welcome message shown when users first open the chat widget. HTML is allowed.', 'iris-ai'); ?>
     372        </p>
     373    <?php
    363374    }
    364375
     
    369380     * @return void
    370381     */
    371     public static function field_show_welcome() {
    372         $value = get_option( 'irisai_show_welcome', true );
    373         ?>
     382    public static function field_show_welcome()
     383    {
     384        $value = get_option('irisai_show_welcome', true);
     385    ?>
    374386        <label>
    375             <input 
    376                 type="checkbox" 
    377                 name="irisai_show_welcome" 
    378                 value="1" 
    379                 <?php checked( $value, true ); ?> />
    380             <?php esc_html_e( 'Show welcome message when widget opens', 'iris-ai' ); ?>
     387            <input
     388                type="checkbox"
     389                name="irisai_show_welcome"
     390                value="1"
     391                <?php checked($value, true); ?> />
     392            <?php esc_html_e('Show welcome message when widget opens', 'iris-ai'); ?>
    381393        </label>
    382394        <p class="description">
    383             <?php esc_html_e( 'Display a friendly welcome message when users first open the chat.', 'iris-ai' ); ?>
    384         </p>
    385         <?php
     395            <?php esc_html_e('Display a friendly welcome message when users first open the chat.', 'iris-ai'); ?>
     396        </p>
     397    <?php
    386398    }
    387399
     
    392404     * @return void
    393405     */
    394     public static function field_show_suggestions_widget() {
    395         $value = get_option( 'irisai_show_suggestions_widget', true );
    396         ?>
     406    public static function field_show_suggestions_widget()
     407    {
     408        $value = get_option('irisai_show_suggestions_widget', true);
     409    ?>
    397410        <label>
    398             <input 
    399                 type="checkbox" 
    400                 name="irisai_show_suggestions_widget" 
    401                 value="1" 
    402                 <?php checked( $value, true ); ?> />
    403             <?php esc_html_e( 'Display suggestion chips in the chat widget', 'iris-ai' ); ?>
     411            <input
     412                type="checkbox"
     413                name="irisai_show_suggestions_widget"
     414                value="1"
     415                <?php checked($value, true); ?> />
     416            <?php esc_html_e('Display suggestion chips in the chat widget', 'iris-ai'); ?>
    404417        </label>
    405418        <p class="description">
     
    407420            printf(
    408421                /* translators: %s: link to general settings */
    409                 esc_html__( 'Show clickable suggestion prompts to help users get started. Configure the suggestions in the %s.', 'iris-ai' ),
    410                 '<a href="' . esc_url( add_query_arg( 'tab', 'general', admin_url( 'admin.php?page=irisai' ) ) ) . '">' . esc_html__( 'General tab', 'iris-ai' ) . '</a>'
     422                esc_html__('Show clickable suggestion prompts to help users get started. Configure the suggestions in the %s.', 'iris-ai'),
     423                '<a href="' . esc_url(add_query_arg('tab', 'general', admin_url('admin.php?page=irisai'))) . '">' . esc_html__('General tab', 'iris-ai') . '</a>'
    411424            );
    412425            ?>
    413426        </p>
    414         <?php
     427    <?php
    415428    }
    416429
     
    421434     * @return void
    422435     */
    423     public static function field_enable_history() {
    424         $value = get_option( 'irisai_enable_history', true );
    425         ?>
     436    public static function field_enable_history()
     437    {
     438        $value = get_option('irisai_enable_history', true);
     439    ?>
    426440        <label>
    427             <input 
    428                 type="checkbox" 
    429                 name="irisai_enable_history" 
    430                 value="1" 
    431                 <?php checked( $value, true ); ?> />
    432             <?php esc_html_e( 'Store chat history in browser localStorage', 'iris-ai' ); ?>
     441            <input
     442                type="checkbox"
     443                name="irisai_enable_history"
     444                value="1"
     445                <?php checked($value, true); ?> />
     446            <?php esc_html_e('Store chat history in browser localStorage', 'iris-ai'); ?>
    433447        </label>
    434448        <p class="description">
    435             <?php esc_html_e( 'When enabled, chat messages persist across page reloads. Users can clear their history with the "New Chat" button.', 'iris-ai' ); ?>
    436         </p>
    437         <?php
     449            <?php esc_html_e('When enabled, chat messages persist across page reloads. Users can clear their history with the "New Chat" button.', 'iris-ai'); ?>
     450        </p>
     451    <?php
    438452    }
    439453
     
    444458     * @return void
    445459     */
    446     public static function field_max_history() {
    447         $value = get_option( 'irisai_max_history', 50 );
    448         ?>
    449         <input
    450             type="number"
    451             name="irisai_max_history"
     460    public static function field_max_history()
     461    {
     462        $value = get_option('irisai_max_history', 50);
     463    ?>
     464        <input
     465            type="number"
     466            name="irisai_max_history"
    452467            id="irisai_max_history"
    453             value="<?php echo esc_attr( $value ); ?>"
    454             min="10" 
    455             max="100" 
     468            value="<?php echo esc_attr($value); ?>"
     469            min="10"
     470            max="100"
    456471            step="10"
    457472            class="small-text" />
    458473        <p class="description">
    459             <?php esc_html_e( 'Maximum number of messages to store in chat history (10-100). Older messages are automatically removed.', 'iris-ai' ); ?>
    460         </p>
    461         <?php
     474            <?php esc_html_e('Maximum number of messages to store in chat history (10-100). Older messages are automatically removed.', 'iris-ai'); ?>
     475        </p>
     476    <?php
    462477    }
    463478
     
    468483     * @return void
    469484     */
    470     public static function field_enable_sources() {
    471         $value = get_option( 'irisai_enable_sources', false );
    472         ?>
     485    public static function field_enable_sources()
     486    {
     487        $value = get_option('irisai_enable_sources', false);
     488    ?>
    473489        <label>
    474             <input 
    475                 type="checkbox" 
    476                 name="irisai_enable_sources" 
    477                 value="1" 
    478                 <?php checked( $value, true ); ?> />
    479             <?php esc_html_e( 'Display source links with AI responses', 'iris-ai' ); ?>
     490            <input
     491                type="checkbox"
     492                name="irisai_enable_sources"
     493                value="1"
     494                <?php checked($value, true); ?> />
     495            <?php esc_html_e('Display source links with AI responses', 'iris-ai'); ?>
    480496        </label>
    481497        <p class="description">
    482             <?php esc_html_e( 'Show clickable source cards below AI answers, linking to the pages where information was found.', 'iris-ai' ); ?>
    483         </p>
    484         <?php
     498            <?php esc_html_e('Show clickable source cards below AI answers, linking to the pages where information was found.', 'iris-ai'); ?>
     499        </p>
     500<?php
    485501    }
    486502
     
    492508     * @return string Sanitized position.
    493509     */
    494     public static function sanitize_widget_position( $value ) {
    495         $allowed = array( 'bottom-right', 'bottom-left', 'top-right', 'top-left' );
    496         return in_array( $value, $allowed, true ) ? $value : 'bottom-right';
     510    public static function sanitize_widget_position($value)
     511    {
     512        $allowed = array('bottom-right', 'bottom-left', 'top-right', 'top-left');
     513        return in_array($value, $allowed, true) ? $value : 'bottom-right';
    497514    }
    498515
     
    504521     * @return int Sanitized value.
    505522     */
    506     public static function sanitize_max_history( $value ) {
    507         $value = absint( $value );
    508         return max( 10, min( 100, $value ) );
     523    public static function sanitize_max_history($value)
     524    {
     525        $value = absint($value);
     526        return max(10, min(100, $value));
    509527    }
    510528}
  • iris-ai/trunk/iris-ai.php

    r3428373 r3447337  
    44 * Plugin Name: Iris AI – AI Homepage, Chatbot & Site Assistant
    55 * Description: AI assistant for WordPress with BYO-key or Proxy mode, chat UI, and content tools.
    6  * Version: 1.0.5
     6 * Version: 2.0.0
    77 * Author: Irisai
    88 * Author URI: https://irisai.cloud
     
    2323
    2424// Plugin constants.
    25 define('IRISAI_VERSION', '1.0.5');
     25define('IRISAI_VERSION', '2.0.0');
    2626define('IRISAI_PATH', plugin_dir_path(__FILE__));
    2727define('IRISAI_URL', plugin_dir_url(__FILE__));
     
    3838require_once IRISAI_PATH . 'includes/class-irisai-vector-db.php';
    3939require_once IRISAI_PATH . 'includes/class-irisai-vector-integration.php';
     40require_once IRISAI_PATH . '/setup-wizard/logic-config-checks.php';
     41require_once IRISAI_PATH . '/setup-wizard/class-irisai-setup-wizard.php';
    4042
    4143/**
     
    397399});
    398400
    399 add_filter( 'render_block', 'irisai_override_theme_hero', 10, 2 );
     401add_filter('render_block', 'irisai_override_theme_hero', 10, 2);
    400402
    401403/**
     
    411413 * @return string
    412414 */
    413 function irisai_override_theme_hero( $block_content, $block ) {
     415function irisai_override_theme_hero($block_content, $block)
     416{
    414417
    415418    // Only modify front-end output (not editor, REST, AJAX, feeds, etc).
    416     if ( is_admin() || wp_doing_ajax() || wp_is_json_request() ) {
     419    if (is_admin() || wp_doing_ajax() || wp_is_json_request()) {
    417420        return $block_content;
    418421    }
    419422
    420423    // Validate expected block structure.
    421     if ( empty( $block['attrs']['metadata']['name'] ) ) {
     424    if (empty($block['attrs']['metadata']['name'])) {
    422425        return $block_content;
    423426    }
    424427
    425428    // Only target the specific theme block.
    426     if ( 'irisaitheme/hero' !== $block['attrs']['metadata']['name'] ) {
     429    if ('irisaitheme/hero' !== $block['attrs']['metadata']['name']) {
    427430        return $block_content;
    428431    }
    429432
    430433    // Only render if the shortcode is available.
    431     if ( ! shortcode_exists( 'irisai_chat' ) ) {
     434    if (! shortcode_exists('irisai_chat')) {
    432435        return $block_content;
    433436    }
    434437
    435438    // Prevent potential recursive rendering.
    436     remove_filter( 'render_block', 'irisai_override_theme_hero', 10 );
    437 
    438     $replacement = do_shortcode( '[irisai_chat]' );
     439    remove_filter('render_block', 'irisai_override_theme_hero', 10);
     440
     441    $replacement = do_shortcode('[irisai_chat]');
    439442
    440443    // Restore filter after rendering.
    441     add_filter( 'render_block', 'irisai_override_theme_hero', 10, 2 );
     444    add_filter('render_block', 'irisai_override_theme_hero', 10, 2);
    442445
    443446    return $replacement;
    444447}
     448
     449/**
     450 * @since 2.0.0
     451 * Setup Wizard Initialization
     452 */
     453
     454new \IrisAI\Admin\Setup_Wizard();
     455
     456
     457register_activation_hook(__FILE__, function () {
     458
     459    if (! get_option('irisai_installed_version')) {
     460        add_option('irisai_do_setup_wizard', 1);
     461    }
     462
     463    update_option('irisai_installed_version', IRISAI_VERSION);
     464});
     465
     466add_action('admin_init', function () {
     467
     468    if (! current_user_can('manage_options')) {
     469        return;
     470    }
     471
     472    // Respect user skip or completion
     473    if (get_option('irisai_setup_completed') || get_option('irisai_setup_dismissed')) {
     474        return;
     475    }
     476
     477    // If fully configured, mark as done and stop
     478    if (function_exists('irisai_is_fully_configured') && irisai_is_fully_configured()) {
     479        update_option('irisai_setup_completed', 1);
     480        return;
     481    }
     482
     483    //  ONLY redirect when user is on THIS PAGE
     484    if (isset($_GET['page']) && $_GET['page'] === 'irisai') {
     485
     486        // But don't redirect if already in wizard
     487        if (isset($_GET['page']) && $_GET['page'] === 'irisai-setup') {
     488            return;
     489        }
     490
     491        wp_safe_redirect(admin_url('admin.php?page=irisai-setup'));
     492        exit;
     493    }
     494});
  • iris-ai/trunk/readme.txt

    r3428373 r3447337  
    22Contributors: zephyrwp
    33Donate link: https://irisai.cloud
    4 Tags: ai, chatbot, openai, assistant, gpt, vector search, semantic search, rag
     4Tags: ai, chatbot, openai, assistant, gpt, semantic search
    55Requires at least: 5.0
    66Tested up to: 6.9
    7 Stable tag: 1.0.5
     7Stable tag: 2.0.0
    88Requires PHP: 7.4
    99License: GPLv2 or later
     
    246246
    247247== Changelog ==
     248= 2.0.0 =
     249Introduces the new Setup Wizard.
    248250= 1.0.5 =
    249251* Responsive style fixes
     
    274276== Upgrade Notice ==
    275277
     278= 2.0.0 =
     279Introduces the new Setup Wizard, improved background indexing system, clearer Proxy/BYO configuration flow, and multiple performance and stability improvements.
     280
    276281= 1.0.5 =
    277282* Fixed issues in responsive mode
Note: See TracChangeset for help on using the changeset viewer.