drakosfire commited on
Commit
f1cc591
2 Parent(s): 9cb5d54 ac9f06d

Merge branch 'main' of github.com:Drakosfire/StoreGenerator

Browse files
Files changed (6) hide show
  1. app.py +0 -0
  2. scripts.js +129 -59
  3. storeUI.css +36 -15
  4. storeUI.html +16 -12
  5. store_helper.py +13 -8
  6. template_update.html +3 -3
app.py CHANGED
File without changes
scripts.js CHANGED
@@ -6,6 +6,7 @@ document.addEventListener("DOMContentLoaded", function() {
6
  const pageContainer = document.getElementById('pages');
7
  const trashArea = document.getElementById('trashArea');
8
  const toggleButton = document.getElementById('toggle-text-block-button');
 
9
  const resetButton = document.getElementById('resetButton');
10
  const addPageButton = document.getElementById('add-page-button');
11
  const removePageButton = document.getElementById('remove-page-button');
@@ -124,7 +125,37 @@ document.addEventListener("DOMContentLoaded", function() {
124
  document.querySelector('.toggle-text-block-button').textContent = 'Hide All Image Descriptions';
125
  }
126
  }
127
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  window.printPageContainer = function(newTab) {
129
  var pageContainer = document.getElementById('brewRenderer');
130
 
@@ -147,9 +178,6 @@ document.addEventListener("DOMContentLoaded", function() {
147
 
148
  .page {
149
  page-break-before: auto;
150
- page-break-after: avoid;
151
- page-break-inside: avoid;
152
-
153
  }
154
  .columnWrapper {
155
  overflow: visible;
@@ -159,7 +187,11 @@ document.addEventListener("DOMContentLoaded", function() {
159
  </style>
160
  </head>
161
  <body>
162
- ${pageContainer.innerHTML}
 
 
 
 
163
  </body>
164
  </html>
165
  `;
@@ -289,10 +321,10 @@ document.addEventListener("DOMContentLoaded", function() {
289
 
290
  storeInitialPositions();
291
 
292
- function adjustTextareaHeight(el) {
293
  if (el.scrollHeight > 16){
294
  el.style.height = 'auto';
295
- el.style.height = (el.scrollHeight) + 'px';
296
  }
297
  }
298
 
@@ -304,10 +336,18 @@ document.addEventListener("DOMContentLoaded", function() {
304
  'properties-textarea',
305
  'string-stat-textarea',
306
  'string-action-description-textarea',
307
- 'image-textarea'
 
308
  ];
309
 
310
  classes.forEach(className => {
 
 
 
 
 
 
 
311
  console.log('Initializing textareas for class:', className);
312
  console.log(document.querySelectorAll(`.${className}`));
313
  const textareas = document.querySelectorAll(`.${className}`);
@@ -315,7 +355,7 @@ document.addEventListener("DOMContentLoaded", function() {
315
  console.log('Textarea found:', textarea);
316
 
317
  // Adjust height on page load
318
- adjustTextareaHeight(textarea);
319
  // Adjust height on input
320
  textarea.addEventListener('input', function() {
321
  adjustTextareaHeight(textarea);
@@ -460,7 +500,7 @@ document.addEventListener("DOMContentLoaded", function() {
460
 
461
  function handleDragStart(e) {
462
  lockTextareas();
463
- const target = e.target.closest('.block-item, .block-content');
464
  if (!target) {
465
  console.error('Drag started for an element without a valid target');
466
  return;
@@ -496,7 +536,7 @@ document.addEventListener("DOMContentLoaded", function() {
496
  }
497
 
498
  function handleDragEnd(e) {
499
- const target = e.target.closest('.block-item, .block-content');
500
  if (target) {
501
  target.style.opacity = '1'; // Reset the opacity
502
  const blockId = target.getAttribute('data-block-id');
@@ -540,7 +580,7 @@ document.addEventListener("DOMContentLoaded", function() {
540
  targetPage.classList.add('highlight-page'); // Add highlight class for pages
541
  }
542
 
543
- const targetBlock = e.target.closest('.block-item, .block-content');
544
  if (targetBlock) {
545
  const bounding = targetBlock.getBoundingClientRect();
546
  const offset = e.clientY - bounding.top;
@@ -557,7 +597,7 @@ document.addEventListener("DOMContentLoaded", function() {
557
  function handleDrop(e) {
558
  e.preventDefault();
559
  // Ensure we are not dropping into a textarea or another block
560
- if (e.target.classList.contains('block-item', 'block-content', 'description-textarea') || e.target.tagName === 'TEXTAREA') {
561
  console.log('Cannot drop block inside another block or textarea');
562
  return;
563
  }
@@ -580,7 +620,7 @@ document.addEventListener("DOMContentLoaded", function() {
580
  }
581
 
582
  const newBlockContent = document.createElement('div');
583
- newBlockContent.classList.add('block-content');
584
  newBlockContent.innerHTML = originalBlock.innerHTML; // Transfer inner content only
585
 
586
  // Add necessary attributes and event listeners
@@ -591,7 +631,7 @@ document.addEventListener("DOMContentLoaded", function() {
591
  newBlockContent.addEventListener('dragstart', handleDragStart);
592
  newBlockContent.addEventListener('dragend', handleDragEnd);
593
 
594
- const target = e.target.closest('.block-item, .block-content');
595
  let targetColumn = 1;
596
  if (target) {
597
  const bounding = target.getBoundingClientRect();
@@ -666,7 +706,7 @@ document.addEventListener("DOMContentLoaded", function() {
666
  // Function to get the height of a column by index
667
  function getColumnHeights(pageElement) {
668
  const columns = [0, 0]; // Assuming two columns for simplicity
669
- const blocks = pageElement.querySelectorAll('.block-content');
670
  blocks.forEach(block => {
671
  const column = getColumnFromOffset(block, block.getBoundingClientRect().left);
672
  columns[column - 1] += block.offsetHeight;
@@ -726,7 +766,7 @@ document.addEventListener("DOMContentLoaded", function() {
726
 
727
  if (pages.length > 1) { // Ensure at least one page remains
728
  const lastPage = pages[pages.length - 1];
729
- const blocks = lastPage.querySelectorAll('.block-content'); // Check for blocks inside the last page
730
 
731
  if (blocks.length > 0) {
732
  // If blocks are present, block the removal and display a warning
@@ -744,7 +784,7 @@ document.addEventListener("DOMContentLoaded", function() {
744
 
745
  function handleColumnOverflow(page, targetColumn) {
746
  console.log(`Handling overflow for page ID: ${page.getAttribute('data-page-id')} in column ${targetColumn}`);
747
- const blocks = Array.from(page.querySelectorAll('.block-content'));
748
  let columnHeights = [0, 0];
749
  let overflowStartIndex = -1;
750
 
@@ -767,7 +807,7 @@ document.addEventListener("DOMContentLoaded", function() {
767
  // Get the next page if it exists
768
  const nextPage = getNextPage(page);
769
  if (nextPage) {
770
- const nextPageBlocks = nextPage.querySelectorAll('.block-content, .block-item');
771
  let nextPageColumnHeights = [0, 0];
772
 
773
  nextPageBlocks.forEach(block => {
@@ -821,7 +861,7 @@ document.addEventListener("DOMContentLoaded", function() {
821
 
822
  if (innerHTML && blockId) {
823
  // Find the dragged element and remove it from the DOM
824
- let draggedElement = document.querySelector(`[data-block-id="${blockId}"].block-content`);
825
  if (!draggedElement) {
826
  draggedElement = document.querySelector(`[data-block-id="${blockId}"].block-item`);
827
  }
@@ -831,7 +871,7 @@ document.addEventListener("DOMContentLoaded", function() {
831
  }
832
 
833
  // Check if the block already exists in the block-container and remove it if it does
834
- let existingBlock = blockContainer.querySelector(`[data-block-id="${blockId}"].block-content`);
835
  if (!existingBlock) {
836
  existingBlock = blockContainer.querySelector(`[data-block-id="${blockId}"].block-item`);
837
  }
@@ -877,62 +917,92 @@ document.addEventListener("DOMContentLoaded", function() {
877
  }
878
 
879
  function handleReset() {
880
- console.log('Reset button clicked');
 
 
 
 
 
 
 
881
 
882
- // Collect all blocks from all pages
883
- const allBlocks = [];
884
- const pages = document.querySelectorAll('.page');
885
- pages.forEach(page => {
886
- const blocksOnPage = page.querySelectorAll('[data-block-id]');
887
- blocksOnPage.forEach(block => {
888
- const blockId = block.getAttribute('data-block-id');
889
- allBlocks.push({
890
- id: blockId,
891
- innerHTML: block.innerHTML
892
- });
893
- block.remove();
894
- console.log(`Removed block with ID: ${blockId} from page ID: ${page.getAttribute('data-page-id')}`);
895
  });
 
 
896
  });
 
 
 
 
 
 
 
 
 
 
897
 
898
- // Clear all pages
899
- pages.forEach(page => page.remove());
 
900
 
901
- // Clear blockContainer before reinserting blocks
902
- blockContainer.innerHTML = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
903
 
904
- // Reinsert blocks back into the blockContainer in their original order
 
 
905
 
906
- if (!blockContainerPage) {
907
- blockContainerPage = document.createElement('div');
908
- blockContainerPage.classList.add('page');
909
- blockContainerPage.setAttribute('id', 'block-page');
910
- blockContainer.appendChild(blockContainerPage);
 
911
  }
912
- // Reassign blockContainerPage to the newly created block-page element
913
- blockContainerPage = document.getElementById('block-page');
914
-
915
- initialPositions.forEach(pos => {
916
- const blockData = allBlocks.find(block => block.id === pos.id);
917
- if (blockData) {
918
- reinsertBlock(blockContainerPage, blockData.id, blockData.innerHTML);
919
- sortBlocksById();
920
- }
921
- });
922
- addPage();
923
 
924
- console.log('Reset complete, all blocks moved back to block-container');
925
- initializeTextareaResizing();
926
- }
927
 
 
 
 
 
 
928
  addPageButton.addEventListener('click', addPage);
929
  removePageButton.addEventListener('click', removePage);
930
  toggleButton.addEventListener('click', toggleAllTextBlocks);
 
 
 
931
  blockContainer.addEventListener('dragover', handleDragOver);
932
  blockContainer.addEventListener('drop', handleDrop);
933
  pageContainer.addEventListener('dragover', handleDragOver);
934
  pageContainer.addEventListener('drop', handleDrop);
935
 
 
936
  trashArea.addEventListener('dragover', handleTrashOver);
937
  trashArea.addEventListener('dragleave', handleTrashLeave);
938
  trashArea.addEventListener('drop', handleTrashDrop);
 
6
  const pageContainer = document.getElementById('pages');
7
  const trashArea = document.getElementById('trashArea');
8
  const toggleButton = document.getElementById('toggle-text-block-button');
9
+ const autofillButton = document.getElementById('autofill-button');
10
  const resetButton = document.getElementById('resetButton');
11
  const addPageButton = document.getElementById('add-page-button');
12
  const removePageButton = document.getElementById('remove-page-button');
 
125
  document.querySelector('.toggle-text-block-button').textContent = 'Hide All Image Descriptions';
126
  }
127
  }
128
+ function autofillBlocks() {
129
+ console.log('Autofill button clicked');
130
+
131
+ const blocks = Array.from(blockContainer.querySelectorAll('.block-item'));
132
+ let currentPage = pageContainer.querySelector('.page');
133
+ // If no existing page is found, create the first page
134
+ if (!currentPage) {
135
+ currentPage = addPage();
136
+ console.log('No existing pages found. Created the first page:', currentPage.id);
137
+ }
138
+
139
+ // Iterate over each block and move it to the pageContainer
140
+ blocks.forEach(block => {
141
+ block.setAttribute('class', 'block-page');
142
+ block.setAttribute('data-page-id', currentPage.getAttribute('data-page-id'));
143
+ // Append the block to the current page's columnWrapper
144
+ const newPage = currentPage.querySelector('.block.monster.frame.wide');
145
+ newPage.appendChild(block);
146
+ console.log(`Moved block with ID: ${block.getAttribute('data-block-id')} to page with ID: ${currentPage.getAttribute('data-page-id')}`);
147
+ // Adjust the layout after adding the block; this function handles creating a new page if needed
148
+ adjustPageLayout(currentPage.getAttribute('data-page-id'));
149
+
150
+ // Check if a new page was created and update curtrrentPage accordingly
151
+ const lastPageInContainer = pageContainer.querySelector('.page:last-child');
152
+ if (lastPageInContainer !== currentPage) {
153
+ currentPage = lastPageInContainer;
154
+ console.log('Moved to a new page:', currentPage.getAttribute('data-page-id'));
155
+ }
156
+ });
157
+ console.log('Autofill complete, all blocks moved to page-container');
158
+ }
159
  window.printPageContainer = function(newTab) {
160
  var pageContainer = document.getElementById('brewRenderer');
161
 
 
178
 
179
  .page {
180
  page-break-before: auto;
 
 
 
181
  }
182
  .columnWrapper {
183
  overflow: visible;
 
187
  </style>
188
  </head>
189
  <body>
190
+ <div id="pageContainer" class="page-container">
191
+ <div id= "brewRenderer" class="brewRenderer">
192
+ ${pageContainer.innerHTML}
193
+ </div>
194
+ </div>
195
  </body>
196
  </html>
197
  `;
 
321
 
322
  storeInitialPositions();
323
 
324
+ function adjustTextareaHeight(el, offset = 0) {
325
  if (el.scrollHeight > 16){
326
  el.style.height = 'auto';
327
+ el.style.height = (el.scrollHeight) + offset + 'px';
328
  }
329
  }
330
 
 
336
  'properties-textarea',
337
  'string-stat-textarea',
338
  'string-action-description-textarea',
339
+ 'image-textarea',
340
+ 'title-textarea'
341
  ];
342
 
343
  classes.forEach(className => {
344
+ if (className === 'description-textarea') {
345
+ console.log('Class is ', className, 'offset is 5');
346
+ offset = 10;
347
+ } else {
348
+ offset = 0;
349
+ }
350
+
351
  console.log('Initializing textareas for class:', className);
352
  console.log(document.querySelectorAll(`.${className}`));
353
  const textareas = document.querySelectorAll(`.${className}`);
 
355
  console.log('Textarea found:', textarea);
356
 
357
  // Adjust height on page load
358
+ adjustTextareaHeight(textarea, offset);
359
  // Adjust height on input
360
  textarea.addEventListener('input', function() {
361
  adjustTextareaHeight(textarea);
 
500
 
501
  function handleDragStart(e) {
502
  lockTextareas();
503
+ const target = e.target.closest('.block-item, .block-page');
504
  if (!target) {
505
  console.error('Drag started for an element without a valid target');
506
  return;
 
536
  }
537
 
538
  function handleDragEnd(e) {
539
+ const target = e.target.closest('.block-item, .block-page');
540
  if (target) {
541
  target.style.opacity = '1'; // Reset the opacity
542
  const blockId = target.getAttribute('data-block-id');
 
580
  targetPage.classList.add('highlight-page'); // Add highlight class for pages
581
  }
582
 
583
+ const targetBlock = e.target.closest('.block-item, .block-page');
584
  if (targetBlock) {
585
  const bounding = targetBlock.getBoundingClientRect();
586
  const offset = e.clientY - bounding.top;
 
597
  function handleDrop(e) {
598
  e.preventDefault();
599
  // Ensure we are not dropping into a textarea or another block
600
+ if (e.target.classList.contains('block-item', 'block-page', 'description-textarea') || e.target.tagName === 'TEXTAREA') {
601
  console.log('Cannot drop block inside another block or textarea');
602
  return;
603
  }
 
620
  }
621
 
622
  const newBlockContent = document.createElement('div');
623
+ newBlockContent.classList.add('block-page');
624
  newBlockContent.innerHTML = originalBlock.innerHTML; // Transfer inner content only
625
 
626
  // Add necessary attributes and event listeners
 
631
  newBlockContent.addEventListener('dragstart', handleDragStart);
632
  newBlockContent.addEventListener('dragend', handleDragEnd);
633
 
634
+ const target = e.target.closest('.block-item, .block-page');
635
  let targetColumn = 1;
636
  if (target) {
637
  const bounding = target.getBoundingClientRect();
 
706
  // Function to get the height of a column by index
707
  function getColumnHeights(pageElement) {
708
  const columns = [0, 0]; // Assuming two columns for simplicity
709
+ const blocks = pageElement.querySelectorAll('.block-page');
710
  blocks.forEach(block => {
711
  const column = getColumnFromOffset(block, block.getBoundingClientRect().left);
712
  columns[column - 1] += block.offsetHeight;
 
766
 
767
  if (pages.length > 1) { // Ensure at least one page remains
768
  const lastPage = pages[pages.length - 1];
769
+ const blocks = lastPage.querySelectorAll('.block-page'); // Check for blocks inside the last page
770
 
771
  if (blocks.length > 0) {
772
  // If blocks are present, block the removal and display a warning
 
784
 
785
  function handleColumnOverflow(page, targetColumn) {
786
  console.log(`Handling overflow for page ID: ${page.getAttribute('data-page-id')} in column ${targetColumn}`);
787
+ const blocks = Array.from(page.querySelectorAll('.block-page'));
788
  let columnHeights = [0, 0];
789
  let overflowStartIndex = -1;
790
 
 
807
  // Get the next page if it exists
808
  const nextPage = getNextPage(page);
809
  if (nextPage) {
810
+ const nextPageBlocks = nextPage.querySelectorAll('.block-page, .block-item');
811
  let nextPageColumnHeights = [0, 0];
812
 
813
  nextPageBlocks.forEach(block => {
 
861
 
862
  if (innerHTML && blockId) {
863
  // Find the dragged element and remove it from the DOM
864
+ let draggedElement = document.querySelector(`[data-block-id="${blockId}"].block-page`);
865
  if (!draggedElement) {
866
  draggedElement = document.querySelector(`[data-block-id="${blockId}"].block-item`);
867
  }
 
871
  }
872
 
873
  // Check if the block already exists in the block-container and remove it if it does
874
+ let existingBlock = blockContainer.querySelector(`[data-block-id="${blockId}"].block-page`);
875
  if (!existingBlock) {
876
  existingBlock = blockContainer.querySelector(`[data-block-id="${blockId}"].block-item`);
877
  }
 
917
  }
918
 
919
  function handleReset() {
920
+ console.log('Reset button clicked');
921
+
922
+ // Collect all blocks from all pages
923
+ const allBlocks = [];
924
+ const pages = document.querySelectorAll('.page');
925
+
926
+ pages.forEach(page => {
927
+ console.log(`Processing page with ID: ${page.getAttribute('data-page-id')}`);
928
 
929
+ const blocksOnPage = page.querySelectorAll('[data-block-id]');
930
+
931
+ blocksOnPage.forEach(block => {
932
+ block.setAttribute('display', 'block');
933
+ const blockId = block.getAttribute('data-block-id');
934
+ allBlocks.push({
935
+ id: blockId,
936
+ innerHTML: block.innerHTML
 
 
 
 
 
937
  });
938
+ block.remove();
939
+ console.log(`Removed block with ID: ${blockId} from page ID: ${page.getAttribute('data-page-id')}`);
940
  });
941
+ });
942
+
943
+ // Log blocks collected
944
+ console.log('All blocks collected:', allBlocks);
945
+
946
+ // Clear all pages
947
+ pages.forEach(page => {
948
+ console.log(`Removing page with ID: ${page.getAttribute('data-page-id')}`);
949
+ page.remove();
950
+ });
951
 
952
+ // Clear blockContainer before reinserting blocks
953
+ console.log('Clearing blockContainer...');
954
+ blockContainer.innerHTML = '';
955
 
956
+ // Check and create blockContainerPage if it doesn't exist
957
+ let blockContainerPage = document.getElementById('block-page');
958
+ if (!blockContainerPage) {
959
+ blockContainerPage = document.createElement('div');
960
+ blockContainerPage.classList.add('page');
961
+ blockContainerPage.setAttribute('id', 'block-page');
962
+ blockContainer.appendChild(blockContainerPage);
963
+ console.log('Created new blockContainerPage');
964
+ } else {
965
+ console.log('blockContainerPage already exists');
966
+ }
967
+
968
+ // Reassign blockContainerPage to the newly created block-page element
969
+
970
+ console.log('blockContainerPage reassigned to:', blockContainerPage);
971
 
972
+ // Reinsert blocks back into the blockContainer in their original order
973
+ initialPositions.forEach(pos => {
974
+ const blockData = allBlocks.find(block => block.id === pos.id);
975
 
976
+ if (blockData) {
977
+ console.log(`Reinserting block with ID: ${blockData.id} into blockContainerPage`);
978
+ reinsertBlock(blockContainerPage, blockData.id, blockData.innerHTML);
979
+ sortBlocksById();
980
+ } else {
981
+ console.log(`Block with ID: ${pos.id} not found in collected blocks.`);
982
  }
983
+ });
 
 
 
 
 
 
 
 
 
 
984
 
985
+ // Add a new page after reset
986
+ addPage();
987
+ console.log('Added new page after reset.');
988
 
989
+ console.log('Reset complete, all blocks moved back to block-container');
990
+ initializeTextareaResizing();
991
+ }
992
+
993
+ // Event listeners for buttons
994
  addPageButton.addEventListener('click', addPage);
995
  removePageButton.addEventListener('click', removePage);
996
  toggleButton.addEventListener('click', toggleAllTextBlocks);
997
+ autofillButton.addEventListener('click', autofillBlocks);
998
+
999
+ // Event listeners for drag and drop functionality
1000
  blockContainer.addEventListener('dragover', handleDragOver);
1001
  blockContainer.addEventListener('drop', handleDrop);
1002
  pageContainer.addEventListener('dragover', handleDragOver);
1003
  pageContainer.addEventListener('drop', handleDrop);
1004
 
1005
+ // Event listeners for trash area
1006
  trashArea.addEventListener('dragover', handleTrashOver);
1007
  trashArea.addEventListener('dragleave', handleTrashLeave);
1008
  trashArea.addEventListener('drop', handleTrashDrop);
storeUI.css CHANGED
@@ -51,35 +51,52 @@
51
 
52
  }
53
  .page-container {
54
- margin-left: 450px; /* Offset the page content by the width of block-container plus margin */
55
- width: 900px;
56
- padding: 20px;
57
- overflow: auto; /* Enable scrolling if needed */
58
- height: 100vh; /* Full viewport height */
59
- box-sizing: border-box; /* Include padding and border in the element's total width and height */
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  @media print {
63
 
64
  .page {
65
  page-break-before: auto;
66
- page-break-after: avoid;
67
- page-break-inside: avoid;
68
 
69
  }
70
  .columnWrapper {
71
  overflow: visible;
72
  }
73
- .block-content {
74
  margin-bottom: 0;
75
  }
76
  }
77
-
78
 
79
  .page {
80
  column-count: 2;
81
  column-gap: .9cm;
82
  column-width: 8cm;
 
83
  -webkit-column-count: 2;
84
  -moz-column-count: 2;
85
  -webkit-column-width: 8cm;
@@ -134,13 +151,17 @@
134
  margin-left: 0.1cm;
135
  }
136
 
 
 
 
137
  /* Ensure the h1 tag is constrained within its column */
138
- .block-content h1 {
139
  column-span: none;
140
  box-sizing: border-box; /* Include padding and border in the element's total width and height */
141
  margin: 0 auto; /* Center the h1 within the column */
142
  overflow: hidden; /* Handle overflow content */
143
  word-wrap: break-word; /* Break long words to prevent overflow */
 
144
  }
145
  .columnWrapper {
146
  width: 100%;
@@ -495,14 +516,14 @@
495
  display: none; /* Hidden by default when in .page-container */
496
  }
497
 
498
- .page-container .block-content:hover .image-textarea {
499
- display: block; /* Show when hovering over .block-content */
500
  }
501
  .page-container .generate-image-button {
502
  display: none; /* Hidden by default when in .page-container */
503
  }
504
 
505
- .page-container .block-content:hover .generate-image-button {
506
  display: inline-block; /* Show the button on hover */
507
  }
508
 
 
51
 
52
  }
53
  .page-container {
54
+ margin-left: 450px; /* Offset the page content by the width of block-container plus margin */
55
+ width: 900px;
56
+ padding: 20px;
57
+ padding-top: 100px; /* Adjust based on the toolbar's height + any additional space you want */
58
+ overflow: auto; /* Enable scrolling if needed */
59
+ height: calc(100vh - 80px); /* Adjust the height to consider the toolbar's height */
60
+ box-sizing: border-box; /* Include padding and border in the element's total width and height */
61
+ }
62
+
63
+ #floatingToolbar {
64
+ position: fixed;
65
+ column-count: 2;
66
+ column-width: 425px;
67
+ column-fill: auto;
68
+ width: 900px; /* Set the width of the floating toolbar */
69
+ top: 10px; /* Distance from the top of the page */
70
+ left: 475px; /* Distance from the right side of the page */
71
+ z-index: 1000; /* Ensure it stays on top of other elements */
72
+ background-color: #f9f9f9; /* Optional: Background color */
73
+ padding: 10px;
74
+ box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); /* Optional: Shadow for a floating effect */
75
+ border-radius: 8px; /* Optional: Rounded corners */
76
+ height: 135px; /* Set the height of the floating toolbar */
77
+ }
78
+
79
 
80
  @media print {
81
 
82
  .page {
83
  page-break-before: auto;
84
+
 
85
 
86
  }
87
  .columnWrapper {
88
  overflow: visible;
89
  }
90
+ .block-page {
91
  margin-bottom: 0;
92
  }
93
  }
 
94
 
95
  .page {
96
  column-count: 2;
97
  column-gap: .9cm;
98
  column-width: 8cm;
99
+ column-fill: auto;
100
  -webkit-column-count: 2;
101
  -moz-column-count: 2;
102
  -webkit-column-width: 8cm;
 
151
  margin-left: 0.1cm;
152
  }
153
 
154
+ .block-page{
155
+ break-inside: avoid;
156
+ }
157
  /* Ensure the h1 tag is constrained within its column */
158
+ .block-page h1 {
159
  column-span: none;
160
  box-sizing: border-box; /* Include padding and border in the element's total width and height */
161
  margin: 0 auto; /* Center the h1 within the column */
162
  overflow: hidden; /* Handle overflow content */
163
  word-wrap: break-word; /* Break long words to prevent overflow */
164
+
165
  }
166
  .columnWrapper {
167
  width: 100%;
 
516
  display: none; /* Hidden by default when in .page-container */
517
  }
518
 
519
+ .page-container .block-page:hover .image-textarea {
520
+ display: block; /* Show when hovering over .block-page */
521
  }
522
  .page-container .generate-image-button {
523
  display: none; /* Hidden by default when in .page-container */
524
  }
525
 
526
+ .page-container .block-page:hover .generate-image-button {
527
  display: inline-block; /* Show the button on hover */
528
  }
529
 
storeUI.html CHANGED
@@ -21,19 +21,23 @@
21
  <!-- Blocks will be wrapped in a page div and loaded here -->
22
  </div>
23
  </div>
24
-
25
- <div class="page-container" id="pageContainer">
26
  <h1>Describe your creature</h1>
27
- <textarea id="user-description" class="user-description-textarea"
28
- hx-post="/update-stats" hx-trigger="change"
29
- hx-target="#user-description" hx-swap="outerHTML"
30
- title="As much or as little description as you want to provide. You can provide specific employees, inventory etc">A very standard gear store run by a fae potted plant named Gorgeous</textarea>
31
- <button id="submitDescription">Submit</button>
32
- <button id="toggle-text-block-button">Toggle Image Descriptions</button>
33
- <button id="add-page-button">Add New Page</button>
34
- <button id="remove-page-button">Remove Last Page</button>
35
- <button id="resetButton">Reset</button>
36
- <button id="printButton">Open Tab to print</button>
 
 
 
 
 
37
  <div class="brewRenderer" id="brewRenderer">
38
 
39
  <div class="pages" id="pages">
 
21
  <!-- Blocks will be wrapped in a page div and loaded here -->
22
  </div>
23
  </div>
24
+ <div id="floatingToolbar">
 
25
  <h1>Describe your creature</h1>
26
+ <textarea id="user-description" class="user-description-textarea"
27
+ hx-post="/update-stats" hx-trigger="change"
28
+ hx-target="#user-description" hx-swap="outerHTML"
29
+ title="As much or as little description as you want to provide. You can provide specific employees, inventory etc">A very standard gear store run by a fae potted plant named Gorgeous</textarea>
30
+ <button id="submitDescription">Submit</button>
31
+ <button id="autofill-button">Autofill Pages</button>
32
+ <button id="toggle-text-block-button">Toggle Image Descriptions</button>
33
+ <button id="add-page-button">Add New Page</button>
34
+ <button id="remove-page-button">Remove Last Page</button>
35
+ <button id="resetButton">Reset</button>
36
+ <button id="printButton">Open Tab to print</button>
37
+ </div>
38
+ <div class="page-container" id="pageContainer">
39
+
40
+
41
  <div class="brewRenderer" id="brewRenderer">
42
 
43
  <div class="pages" id="pages">
store_helper.py CHANGED
@@ -78,24 +78,29 @@ def convert_to_dict(string):
78
 
79
 
80
  # Instructions past 4 are not time tested and may need to be removed.
81
- ### Meta prompted :
82
  initial_prompt_instructions = """ **Purpose**: ONLY Generate a structured json following the provided format. The job is to generate a store with character, style, detail, and a healthy splash of fun, fantasy, and weird. You do not need to stick strictly to the rules and mechanics of the game, if it fits the style and flavor of the user input, get weird, scary, or silly with the details. You will also be writing interesting flavor text and description of the location and it's atmopshere, and a brief one sentence image generation prompts. Us a wide range of words, you have certain words you use too often, avoid them ex : "whimsical", "unwavering".
83
 
84
- Image Generation Prompt Examples :
85
- "A highly detailed fantasy oil painting of an elderly full body female gnome,in a costume shop. The gnome is wearing a costume with wings, with a costume hat . The gnome has distinct fantasy features, such as pointed ears and a small, sturdy build. "
86
 
87
- "A highly detailed fantasy drawing of a middle-aged full body male dwarf in a bustling butcher shop. The dwarf is wearing a bloodstained apron and a butcher's hat. The shop is filled with hanging meats, freshly cut steaks, and various sausages. The dwarf has distinct fantasy features, such as a long braided beard and a stout, muscular build. The background shows the hustle and bustle of Market Square outside the shop window."
 
88
 
89
- "A highly detailed fantasy image of a shady-looking full body male goblin in a dimly lit pawn shop. The goblin is wearing a patched vest and a tattered hat. The shop is cluttered with various items, including old weapons, dusty artifacts, and strange trinkets. The goblin has distinct fantasy features, such as green skin, sharp teeth, and pointed ears. The background is filled with shadows and the glint of hidden treasures."
90
 
91
- "A highly detailed fantasy photo of a scholarly full body female elf in an elegant parchment shop. The elf is wearing a flowing robe and a delicate circlet. The shop is filled with scrolls, quills, and ancient tomes. The elf has distinct fantasy features, such as pointed ears and a slender, graceful build. The background shows the interior of the shop with shelves lined with parchment and ink bottles, and a large window letting in natural light."
92
 
93
- "A highly detailed fantasy painting of a mysterious full body male tiefling in a mystical magic shop. The tiefling is wearing a long cloak and a hood, with glowing runes on his hands. The shop is filled with potions, spellbooks, and enchanted artifacts. The tiefling has distinct fantasy features, such as red skin, horns, and a tail. The background is filled with a magical aura, with various mystical items floating in the air and a crystal ball on the counter."
 
 
 
 
 
94
 
95
  1. Only output file structure starting with { and ending with } it is CRITICAL to end with a }, DO NOT say anything, don't add ''' or json"
96
  2. DO NOT use null, use "".
97
  3. All keys and values MUST be enclosed in double quotes. ""
98
- 4. Services and specialties should have name, description, and prices.
99
  5. sd_prompts should specify race or species
100
  6. quests MUST be detailed, and interesting, preferably unexpected, delightful and memorable.
101
  7. The reward for the quest MUST be specific and detailed!
 
78
 
79
 
80
  # Instructions past 4 are not time tested and may need to be removed.
81
+ ### System prompt :
82
  initial_prompt_instructions = """ **Purpose**: ONLY Generate a structured json following the provided format. The job is to generate a store with character, style, detail, and a healthy splash of fun, fantasy, and weird. You do not need to stick strictly to the rules and mechanics of the game, if it fits the style and flavor of the user input, get weird, scary, or silly with the details. You will also be writing interesting flavor text and description of the location and it's atmopshere, and a brief one sentence image generation prompts. Us a wide range of words, you have certain words you use too often, avoid them ex : "whimsical", "unwavering".
83
 
84
+ store_front_sd_prompt should be from the exterior, emphasize the store's architecture, style, and atmosphere and exclude descriptions of the owner.
 
85
 
86
+ storefront_sd_prompt Examples :
87
+ "A highly detailed fantasy painting of the exterior of a bustling magic shop. The shop is adorned with glowing runes, enchanted crystals, and mystical artifacts. The shop sign reads "Arcane Emporium" in elegant script. The street is filled with magical creatures, floating lanterns, and colorful stalls. "
88
 
89
+ "A highly detailed fantasy drawing of the entrance to a mysterious alchemy shop. The shop is hidden down a narrow alley, with a flickering lantern above the door. The shop sign reads "Elixir Emporium" in faded letters. The alley is filled with shadows, strange smells, and the distant sound of bubbling potions. "
90
 
91
+ "A highly detailed fantasy photo of the front of a grand weapon shop. The shop is decorated with suits of armor, hanging banners, and a large sword embedded in the stone facade. The shop sign reads "Ironclad Armory" in bold letters. The street is filled with armored guards, clashing swords, and the sound of ringing anvils. "
92
 
93
+ Owner and Employee Generation Prompt Examples :
94
+ "A highly detailed fantasy oil painting portrait of a wise and mysterious shop owner. The owner is an elderly elf with silver hair, a long beard, and piercing blue eyes. They wear flowing robes, a jeweled amulet, and a crown of thorns. The owner is surrounded by magical artifacts, ancient tomes, and glowing crystals."
95
+
96
+ "A highly detailed fantasy charcoal sketch of a quirky and eccentric shop employee. The employee is a young gnome with wild hair, mismatched eyes, and a mischievous grin. They wear patched clothes, a bandolier of potions, and a pet dragon perched on their shoulder. The employee is surrounded by alchemical ingredients, bubbling cauldrons, and floating spellbooks."
97
+
98
+ "A highly detailed fantasy watercolor painting of a stoic and intimidating shop security guard. The guard is a massive half-orc with a shaved head, a scarred face, and a stern expression. They wear heavy armor, a massive sword, and a shield emblazoned with a roaring lion. The guard is surrounded by chained beasts, locked chests, and glowing runes."
99
 
100
  1. Only output file structure starting with { and ending with } it is CRITICAL to end with a }, DO NOT say anything, don't add ''' or json"
101
  2. DO NOT use null, use "".
102
  3. All keys and values MUST be enclosed in double quotes. ""
103
+ 4. Services and specialties should have name, description, and prices.
104
  5. sd_prompts should specify race or species
105
  6. quests MUST be detailed, and interesting, preferably unexpected, delightful and memorable.
106
  7. The reward for the quest MUST be specific and detailed!
template_update.html CHANGED
@@ -9,7 +9,7 @@
9
  </div>
10
 
11
  <div class="block-item" data-block-id="1" data-page-id="block-container" draggable="true">
12
- <textarea class="image-textarea" id="user-storefront-prompt-1" hx-post="/update-stats" hx-trigger="change" hx-target="#user-sd-prompt" hx-swap="outerHTML" title="Storefront image description" style="height: 80px;">A highly detailed fantasy painting of a curious sentient potted plant in a vibrant gear shop. The plant has phosphorescent leaves and delicate, intricate roots. The shop is filled with glowing flora, magical tools, and adventure gear. The background shows enchanted trees intertwined with the walls and ceiling.</textarea>
13
  <button class="generate-image-button" data-block-id="1">Generate Image</button>
14
  <img id="generated-image-1" alt="" style="display: none; cursor: pointer;">
15
  </div>
@@ -75,7 +75,7 @@
75
  </div>
76
 
77
  <div class="block-item" data-block-id="3" data-page-id="block-container" draggable="true">
78
- <textarea class="image-textarea" id="user-storefront-prompt-3" hx-post="/update-stats" hx-trigger="change" hx-target="#user-sd-prompt" hx-swap="outerHTML" title="Storefront image description" style="height: 48px;">A highly detailed fantasy drawing of a sentient potted plant with glowing tendrils, set in an enchanting gear shop filled with vibrant flora and a myriad of magical items.</textarea>
79
  <button class="generate-image-button" data-block-id="3">Generate Image</button>
80
  <img id="generated-image-3" alt="" style="display: none; cursor: pointer;">
81
  </div>
@@ -124,7 +124,7 @@
124
  </div>
125
 
126
  <div class="block-item" data-block-id="5" data-page-id="block-container" draggable="true">
127
- <textarea class=""image-textarea"" id="user-storefront-prompt-5" hx-post="/update-stats" hx-trigger="change" hx-target="#user-sd-prompt" hx-swap="outerHTML" title="Storefront image description" style="height: 49px;">A highly detailed fantasy image of a half-elf shopkeeper with forest-green eyes and flower-adorned hair, set in a magical gear shop filled with glowing plants and enchanted equipment.</textarea>
128
  <button class="generate-image-button" data-block-id="5">Generate Image</button>
129
  <img id="generated-image-5" alt="" style="display: none; cursor: pointer;">
130
  </div>
 
9
  </div>
10
 
11
  <div class="block-item" data-block-id="1" data-page-id="block-container" draggable="true">
12
+ <textarea class="image-textarea" id="sdprompt-1" hx-post="/update-stats" hx-trigger="change" hx-target="#user-sd-prompt" hx-swap="outerHTML" title="Storefront image description" style="height: 80px;">A highly detailed fantasy painting of the exterior of a greenhouse that serves double duty as a adventuring gear shop, that is also a greenhouse and is overflowing with plants as well as equipment</textarea>
13
  <button class="generate-image-button" data-block-id="1">Generate Image</button>
14
  <img id="generated-image-1" alt="" style="display: none; cursor: pointer;">
15
  </div>
 
75
  </div>
76
 
77
  <div class="block-item" data-block-id="3" data-page-id="block-container" draggable="true">
78
+ <textarea class="image-textarea" id="sdprompt-3" hx-post="/update-stats" hx-trigger="change" hx-target="#user-sd-prompt" hx-swap="outerHTML" title="Storefront image description" style="height: 48px;">A highly detailed fantasy drawing of a sentient potted plant with glowing tendrils, set in an enchanting gear shop filled with vibrant flora and a myriad of magical items.</textarea>
79
  <button class="generate-image-button" data-block-id="3">Generate Image</button>
80
  <img id="generated-image-3" alt="" style="display: none; cursor: pointer;">
81
  </div>
 
124
  </div>
125
 
126
  <div class="block-item" data-block-id="5" data-page-id="block-container" draggable="true">
127
+ <textarea class="image-textarea" id="sdprompt-5" hx-post="/update-stats" hx-trigger="change" hx-target="#user-sd-prompt" hx-swap="outerHTML" title="Storefront image description" style="height: 49px;">A highly detailed fantasy image of a half-elf shopkeeper with forest-green eyes and flower-adorned hair, set in a magical gear shop filled with glowing plants and enchanted equipment.</textarea>
128
  <button class="generate-image-button" data-block-id="5">Generate Image</button>
129
  <img id="generated-image-5" alt="" style="display: none; cursor: pointer;">
130
  </div>