Skip to content

Commit

Permalink
Merge pull request #43 from eliataylor/eli
Browse files Browse the repository at this point in the history
See TODO and WARN across `stack/django/oasheets_app` for notices on incomplete features.
  • Loading branch information
eliataylor authored Feb 24, 2025
2 parents d54d509 + 6480883 commit 2628c20
Show file tree
Hide file tree
Showing 51 changed files with 2,905 additions and 94 deletions.
8 changes: 4 additions & 4 deletions .env.public
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ PERMISSIONS_PATH=src/examples/permissions-matrix-demo.csv
DEFAULT_PERMS=IsAuthenticatedOrReadOnly

#### Your API Server protocol:host:port ####
# REACT_APP_API_HOST=https://localapi.oaexample.com:8080
REACT_APP_API_HOST=http://localhost:8080
REACT_APP_API_HOST=https://localapi.oaexample.com:8080
# REACT_APP_API_HOST=http://localhost:8080
# REACT_APP_API_HOST=https://api.oaexample.com

#### Your Webapp URL protocol:host:port ####
# REACT_APP_APP_HOST=https://localhost.oaexample.com:3000
REACT_APP_APP_HOST=http://localhost:3000
REACT_APP_APP_HOST=https://localhost.oaexample.com:3000
# REACT_APP_APP_HOST=http://localhost:3000
# REACT_APP_APP_HOST=https://oaexample.com

# Your API admin login
Expand Down
9 changes: 9 additions & 0 deletions src/appscripts/Menu.gs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @OnlyCurrentDoc */

function onOpen()
{ const ui = SpreadsheetApp.getUi();
ui.createMenu("Wizard")
.addItem('Generate Object Fields', 'popupObjectFields')
.addItem('Generate Permissions Matrix', 'popupPermissionsMatrix')
.addToUi();
}
117 changes: 117 additions & 0 deletions src/appscripts/Objects.gs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
function callMenuForObjects()
{ popupObjectFields(false);
}



function createNewObjects(objects)
{ //add new objects
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sObjects = ss.getSheetByName("Object Fields");
if(!sObjects) throw new Error("Sheet 'Object Fields' not found.");
const colLast = sObjects.getLastColumn();
var rowLast = null;
const copyFrom = sObjects.getRange(2,1,3,colLast);

for(var i=0; i<objects.length; i++)
{ rowLast = sObjects.getLastRow();

sObjects.appendRow([objects[i]]);
sObjects.appendRow(["","ID","","Text",1,1]);
sObjects.appendRow(["","Name","","Text",1,1]);

copyFrom.copyTo(sObjects.getRange(rowLast+1,1,3),{formatOnly: true});
//sObjects.getRange(2,1,1).copyTo(sObjects.getRange(rowLast+1,1,1),{formatOnly: true});
sObjects.getRange(`${rowLast+1}:${rowLast+1}`).setBackground(sObjects.getRange("2:2").getBackground());
//sObjects.getRange(3,1,1).copyTo(sObjects.getRange(rowLast+2,1,1),{formatOnly: true});
//sObjects.getRange(`${rowLast+2}:${rowLast+2}`).setBackground(sObjects.getRange("3:3").getBackground());
//sObjects.getRange(3,1,1).copyTo(sObjects.getRange(rowLast+3,1,1),{formatOnly: true});
//sObjects.getRange(`${rowLast+3}:${rowLast+3}`).setBackground(sObjects.getRange("3:3").getBackground());
sObjects.insertRowAfter(rowLast);
}
}




function popupObjectFields(doPrompt = true)
{ const ui = SpreadsheetApp.getUi();
let objects;

// Prompt the user for a comma-separated list of objects
if(doPrompt)
{ const ui = SpreadsheetApp.getUi();
const response = ui.prompt(
'Generate Object Fields',
'Enter a comma-separated list of objects (e.g., Users, Orders, Products, Reports):',
ui.ButtonSet.OK_CANCEL
);

// Handle the user's response
if (response.getSelectedButton() !== ui.Button.OK) {
ui.alert('Operation cancelled.');
return;
}

objects = response.getResponseText().split(',').map(obj => obj.trim());
if (objects.length === 0 || objects.some(obj => obj === '')) {
ui.alert('Invalid input. Please provide a list of object names.');
return;
}
}else
{ objects = ["Farms", "Bookings", "Reports"];
}

//add new objects
Logger.log("Objects list:\n%s",objects);
createNewObjects(objects);

ui.alert('Object Fields generated successfully!');
}




function generateObjectFieldsFromInput()
{ const ss = SpreadsheetApp.getActiveSpreadsheet();
const sInput = ss.getSheetByName("Inputs");
if(!sInput) throw new Error("Sheet 'Inputs' not found.");

//get input data provided by user
var arrActions = sInput.getRange("A:A").getValues().flat();
arrActions = arrActions.filter(val => {return val !=""});
arrActions.shift();

var arrObjects = sInput.getRange("B:B").getValues().flat();
arrObjects = arrObjects.filter(val => {return val !=""});
arrObjects.shift();

//add new objects
Logger.log("Actions list:\n%s\n\nObjects list:\n%s",arrActions,arrObjects);
createNewObjects(arrObjects);

/*
//create objects in the ObjectFields sheet
const sObjects = ss.getSheetByName("Object Fields");
if(!sObjects) throw new Error("Sheet 'Object Fields' not found.");
var templObjects = sObjects.getDataRange().getValues();
templObjects.shift();
var startRow = null;
var endRow = null;
if(templObjects.length)
{ Logger.log("exisiting rows in objects sheet: %s",templObjects.length+1);
for(var i=0; i<templObjects.length; i++)
{ if(!startRow && templObjects[i][0] != "") startRow = i+2;
else if(startRow && !endRow && templObjects[i][1] == "") endRow = i+2;
if(startRow && endRow) break;
}
Logger.log("rows for new object template is b/w: %s and %s",startRow,endRow);
templObjects = sObjects.getRange(startRow,1,endRow-startRow+1,sObjects.getLastColumn());
Logger.log("template to copy is:\n%s",templObjects.getValues());
}
*/
}



117 changes: 117 additions & 0 deletions src/appscripts/Permissions.gs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
function callMenuForObjects()
{ popupObjectFields(false);
}



function createNewObjects(objects)
{ //add new objects
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sObjects = ss.getSheetByName("Object Fields");
if(!sObjects) throw new Error("Sheet 'Object Fields' not found.");
const colLast = sObjects.getLastColumn();
var rowLast = null;
const copyFrom = sObjects.getRange(2,1,3,colLast);

for(var i=0; i<objects.length; i++)
{ rowLast = sObjects.getLastRow();

sObjects.appendRow([objects[i]]);
sObjects.appendRow(["","ID","","Text",1,1]);
sObjects.appendRow(["","Name","","Text",1,1]);

copyFrom.copyTo(sObjects.getRange(rowLast+1,1,3),{formatOnly: true});
//sObjects.getRange(2,1,1).copyTo(sObjects.getRange(rowLast+1,1,1),{formatOnly: true});
sObjects.getRange(`${rowLast+1}:${rowLast+1}`).setBackground(sObjects.getRange("2:2").getBackground());
//sObjects.getRange(3,1,1).copyTo(sObjects.getRange(rowLast+2,1,1),{formatOnly: true});
//sObjects.getRange(`${rowLast+2}:${rowLast+2}`).setBackground(sObjects.getRange("3:3").getBackground());
//sObjects.getRange(3,1,1).copyTo(sObjects.getRange(rowLast+3,1,1),{formatOnly: true});
//sObjects.getRange(`${rowLast+3}:${rowLast+3}`).setBackground(sObjects.getRange("3:3").getBackground());
sObjects.insertRowAfter(rowLast);
}
}




function popupObjectFields(doPrompt = true)
{ const ui = SpreadsheetApp.getUi();
let objects;

// Prompt the user for a comma-separated list of objects
if(doPrompt)
{ const ui = SpreadsheetApp.getUi();
const response = ui.prompt(
'Generate Object Fields',
'Enter a comma-separated list of objects (e.g., Users, Orders, Products, Reports):',
ui.ButtonSet.OK_CANCEL
);

// Handle the user's response
if (response.getSelectedButton() !== ui.Button.OK) {
ui.alert('Operation cancelled.');
return;
}

objects = response.getResponseText().split(',').map(obj => obj.trim());
if (objects.length === 0 || objects.some(obj => obj === '')) {
ui.alert('Invalid input. Please provide a list of object names.');
return;
}
}else
{ objects = ["Farms", "Bookings", "Reports"];
}

//add new objects
Logger.log("Objects list:\n%s",objects);
createNewObjects(objects);

ui.alert('Object Fields generated successfully!');
}




function generateObjectFieldsFromInput()
{ const ss = SpreadsheetApp.getActiveSpreadsheet();
const sInput = ss.getSheetByName("Inputs");
if(!sInput) throw new Error("Sheet 'Inputs' not found.");

//get input data provided by user
var arrActions = sInput.getRange("A:A").getValues().flat();
arrActions = arrActions.filter(val => {return val !=""});
arrActions.shift();

var arrObjects = sInput.getRange("B:B").getValues().flat();
arrObjects = arrObjects.filter(val => {return val !=""});
arrObjects.shift();

//add new objects
Logger.log("Actions list:\n%s\n\nObjects list:\n%s",arrActions,arrObjects);
createNewObjects(arrObjects);

/*
//create objects in the ObjectFields sheet
const sObjects = ss.getSheetByName("Object Fields");
if(!sObjects) throw new Error("Sheet 'Object Fields' not found.");
var templObjects = sObjects.getDataRange().getValues();
templObjects.shift();
var startRow = null;
var endRow = null;
if(templObjects.length)
{ Logger.log("exisiting rows in objects sheet: %s",templObjects.length+1);
for(var i=0; i<templObjects.length; i++)
{ if(!startRow && templObjects[i][0] != "") startRow = i+2;
else if(startRow && !endRow && templObjects[i][1] == "") endRow = i+2;
if(startRow && endRow) break;
}
Logger.log("rows for new object template is b/w: %s and %s",startRow,endRow);
templObjects = sObjects.getRange(startRow,1,endRow-startRow+1,sObjects.getLastColumn());
Logger.log("template to copy is:\n%s",templObjects.getValues());
}
*/
}



29 changes: 28 additions & 1 deletion src/django/DjangoBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __init__(self, output_dir):
# TODO: personalize the CustomPagination class

def build_django(self, types_path, default_perm):
if types_path or not os.path.exists(types_path):
if types_path is None or not os.path.exists(types_path):
self.json = build_types_from_csv(types_path)
self.build_models()
self.build_serializers()
Expand All @@ -79,6 +79,33 @@ def build_django(self, types_path, default_perm):
logger.warning(f'Cannot find Object Types {types_path}')
sys.exit(0)


# python generate.py chatbot --types=examples/object-fields-demo.csv --output_dir=../stack/django/oasheets_app/fixtures
def build_chatbot_structures(self, types_path):
if types_path is None or not os.path.exists(types_path):
logger.warning(f'Cannot find Object Types {types_path}')
sys.exit(0)

self.json = build_types_from_csv(types_path)

newjson = {
"content_types": []
}

for class_name in self.json:

model_name = create_object_name(class_name)
content_type = {
"name": class_name,
"model": model_name,
"fields": self.json[class_name]
}
newjson["content_types"].append(content_type)

with open(os.path.join(self.output_dir, f'example_schema.json'), 'w') as file:
file.write(json.dumps(newjson, indent=2))


def append_import(self, key, val):
if val not in self.imports[key]:
if isinstance(val, list):
Expand Down
7 changes: 5 additions & 2 deletions src/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate project files based on field types CSV.")
parser.add_argument('command', choices=['django', 'typescript', 'permissions-ts', 'forms'],
parser.add_argument('command', choices=['django', 'typescript', 'permissions-ts', 'forms', 'chatbot'],
help="Target command for the generation.")
parser.add_argument('--types', required=True, help="Path to the Object Types CSV file.")
parser.add_argument('--permissions', required=False, help="Path to the Permissions Matrix CSV file.")
Expand Down Expand Up @@ -38,7 +38,10 @@
logger.info(f"Running command: {command}")
logger.info(f"Output directory: {output_dir}")

if command == 'django':
if command == 'chatbot':
builder = DjangoBuilder(output_dir)
builder.build_chatbot_structures(types_path)
elif command == 'django':
builder = DjangoBuilder(output_dir)
builder.build_django(types_path, default_perm)
# builder.build_permissions(matrix_path, default_perm)
Expand Down
2 changes: 2 additions & 0 deletions stack/django/.env.public
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,5 @@ GITHUB_CLIENT_ID=CHANGEME

LINKEDIN_CLIENT_ID=CHANGEME
LINKEDIN_SECRET=CHANGEME

OPENAI_API_KEY=CHANGEME
4 changes: 2 additions & 2 deletions stack/django/deploy/cloud-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ REQUIRED_VARS=("GCP_PROJECT_ID" \
"TWILIO_ACCOUNT_SID" \
"TWILIO_AUTH_TOKEN" \
"TWILIO_PHONE_NUMBER" \
"OPENAI_API_KEY" \
"GOOGLE_OAUTH_CLIENT_ID" \
"GOOGLE_OAUTH_SECRET" \
"GOOGLE_OAUTH_KEY" )
Expand All @@ -54,8 +55,6 @@ if [[ "${REACT_APP_APP_HOST}" =~ localhost|localapi|:[0-9]+ ]]; then
fi
fi



show_section_header "DEPLOY CLOUD RUN FROM SOURCE"

login_service_account "$GCP_SA_KEY_PATH" "$GCP_PROJECT_ID"
Expand Down Expand Up @@ -104,6 +103,7 @@ gcloud run deploy $GCP_SERVICE_NAME-cloudrun \
--set-secrets LINKEDIN_SECRET=LINKEDIN_SECRET:latest \
--set-secrets EMAIL_HOST_PASSWORD=EMAIL_HOST_PASSWORD:latest \
--set-secrets SPOTIFY_SECRET=SPOTIFY_SECRET:latest \
--set-secrets OPENAI_API_KEY=OPENAI_API_KEY:latest \
--set-secrets DJANGO_SECRET_KEY=DJANGO_SECRET_KEY:latest \
--set-secrets DJANGO_SUPERUSER_PASSWORD=DJANGO_SUPERUSER_PASSWORD:latest \
--set-secrets MYSQL_PASSWORD=MYSQL_PASSWORD:latest \
Expand Down
7 changes: 6 additions & 1 deletion stack/django/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ output=$(python manage.py makemigrations oaexample_app --noinput 2>&1) || {
echo "[OADJANGO] Make migrations output: $output";
}

echo "[OADJANGO] Building oasheets_app migrations"
output=$(python manage.py makemigrations oasheets_app --noinput 2>&1) || {
echo "[OADJANGO] Make migrations output: $output";
}

echo "[OADJANGO] Building all migrations"
output=$(python manage.py makemigrations --noinput 2>&1) || {
echo "[OADJANGO] Make all migrations output: $output";
Expand Down Expand Up @@ -51,7 +56,7 @@ output=$(python manage.py collectstatic --noinput 2>&1) || {
PORT=$(echo "$REACT_APP_API_HOST" | sed -E 's|^https?://[^:/]+:?([0-9]*)/?|\1|')

# Default to 8080 if no port is extracted
if [[ -z "$PORT" ]]; then
if [[ -z "$PORT" || ! "$PORT" =~ ^[0-9]+$ ]]; then
PORT=8080
fi

Expand Down
Loading

0 comments on commit 2628c20

Please sign in to comment.