<commit_before>require 'fileutils'

namespace :project do

  desc "Load project by key. :area param can be 'content','style','workflows', or 'subjects' (or omitted to load all)."
  task :load, [:project_key, :area] => :environment do |task, args|
    args.with_defaults area: 'all'

    # Validate AREA arg:
    if ! ['all','content','style','workflows','subjects'].include? args[:area]
      puts "Unknown AREA given: #{args[:area]}"
      exit
    end

    project = nil
    # Before proceeding to update anything non-core, confirm we have a project to update:
    if ! ['all','content'].include? args[:area]
      project = Project.find_by key: args[:project_key]

      if project.nil?
        if args[:area] != 'all'
          puts "Before updating #{args[:area]} you must create the project using project:load[#{args[:project_key]}]"
        else
          puts "Halting because project not found"
        end
        exit
      end
    end

    # Load content:
    if ['all','content'].include? args[:area]
      project = load_content args[:project_key]
      puts "Done loading content for \"#{project.title}\""
    end


    # DEPRECATED:
    # Should deprecate this because all static assets can now be fetched directly
    # from project/[key]/assets; There is no need to copy js, images, fonts, etc
    # into app/assets. Serving them directly from the project/../assets folder is
    # preferable because it doesn't clutter app/assets, which should be reserved
    # for core application concerns.
    # Nevertheless, I'm keeping this functionality in place so that projects can
    # gracefully deprecate reliance on copied assets.
    #
    # Load custom styling (css,js,images,fonts, etc):
    if ['all','style'].include? args[:area]
      load_styles project
      puts "Done loading style for \"#{project.title}\""
    end
      
    # Load workflows:
    if ['all','workflows'].include? args[:area]
      begin
        # Rake::Task['project:load_workflows'].invoke project.key
        load_workflows project.key
      rescue Exception => e
        puts "ERROR: #{e.inspect}"
      end
      puts "Done loading #{project.workflows.count} workflow(s) into \"#{project.title}\""
    end

    # Load subjects:
    if ['all','subjects'].include? args[:area]
      if ! project.workflows.find_by(name: 'mark')
        puts "Can't load subjects before loading a mark workflow! Run rake project:load[#{project.key},workflows] first"
        exit
      end
      Rake::Task['subjects:load_groups'].invoke(project.key)
      puts "Done loading #{project.subject_sets.count} subject sets into \"#{project.title}\""
    end

    if project.status == 'active'
      puts "'#{project.title}' is active"

    elsif Project.active.count == 0
      puts "Activating '#{project.title}'"
      project.activate!

    else
      puts "____________"
      puts "Another project, '#{Project.active.first.title}', is currently active. To activate '#{project.title}', run:"
      puts "  rake project:activate[#{args[:project_key]}]"
    end
  end

  desc "List projects and active status"
  task :list, [] => :environment do |task, args|
    args.with_defaults area: 'all'

    puts "Listing projects:"
    Project.all.each do |project|
      puts "  [#{project.status == 'active' ? 'active' : ' ' * 6}] #{project.title}"
    end
  end

  desc "Activate a project by key. Only one project may be active at one time."
  task :activate, [:project_key] => :environment do |task, args|
    args.with_defaults area: 'all'

    project = get_project args[:project_key]
    if ! project.nil?
      puts "Activating #{project.title}"
      project.activate!
    end
  end

  def get_project(project_key)
    project = Project.find_by key: project_key
    puts "Failed to find project '#{project_key}'" if project.nil?
    project
  end

  def load_content(project_key)
    project_dir = Rails.root.join('project', project_key)
    project_file_path = "#{project_dir}/project.json"
    project_hash = JSON.parse File.read(project_file_path)

    # load project_file_path
    project = Project.find_or_create_by key: project_key

    # Set all valid fields from hash:
    project_hash = project_hash.inject({}) { |h, (k,v)| h[k] = v if Project.fields.keys.include?(k.to_s); h }
    project.update project_hash

    puts "Created project: #{project.title}"

    # Load pages from content/*:
    content_path = Rails.root.join('project', project_key, 'content')
    puts "Loading pages from #{content_path}:"

    prev_pages = project.pages
    project.pages = []

    Dir.foreach(content_path).each do |file|
      path = Rails.root.join content_path, file
      next if File.directory? path
      next if ! ['.html','.erb','.md'].include? path.extname
      ext = path.extname<commit_msg>add project defaults to ensure project properties overridden with null version if a previous project is saved without a previous field<commit_after>require 'fileutils'

namespace :project do

  desc "Load project by key. :area param can be 'content','style','workflows', or 'subjects' (or omitted to load all)."
  task :load, [:project_key, :area] => :environment do |task, args|
    args.with_defaults area: 'all'

    # Validate AREA arg:
    if ! ['all','content','style','workflows','subjects'].include? args[:area]
      puts "Unknown AREA given: #{args[:area]}"
      exit
    end

    project = nil
    # Before proceeding to update anything non-core, confirm we have a project to update:
    if ! ['all','content'].include? args[:area]
      project = Project.find_by key: args[:project_key]

      if project.nil?
        if args[:area] != 'all'
          puts "Before updating #{args[:area]} you must create the project using project:load[#{args[:project_key]}]"
        else
          puts "Halting because project not found"
        end
        exit
      end
    end

    # Load content:
    if ['all','content'].include? args[:area]
      project = load_content args[:project_key]
      puts "Done loading content for \"#{project.title}\""
    end


    # DEPRECATED:
    # Should deprecate this because all static assets can now be fetched directly
    # from project/[key]/assets; There is no need to copy js, images, fonts, etc
    # into app/assets. Serving them directly from the project/../assets folder is
    # preferable because it doesn't clutter app/assets, which should be reserved
    # for core application concerns.
    # Nevertheless, I'm keeping this functionality in place so that projects can
    # gracefully deprecate reliance on copied assets.
    #
    # Load custom styling (css,js,images,fonts, etc):
    if ['all','style'].include? args[:area]
      load_styles project
      puts "Done loading style for \"#{project.title}\""
    end
      
    # Load workflows:
    if ['all','workflows'].include? args[:area]
      begin
        # Rake::Task['project:load_workflows'].invoke project.key
        load_workflows project.key
      rescue Exception => e
        puts "ERROR: #{e.inspect}"
      end
      puts "Done loading #{project.workflows.count} workflow(s) into \"#{project.title}\""
    end

    # Load subjects:
    if ['all','subjects'].include? args[:area]
      if ! project.workflows.find_by(name: 'mark')
        puts "Can't load subjects before loading a mark workflow! Run rake project:load[#{project.key},workflows] first"
        exit
      end
      Rake::Task['subjects:load_groups'].invoke(project.key)
      puts "Done loading #{project.subject_sets.count} subject sets into \"#{project.title}\""
    end

    if project.status == 'active'
      puts "'#{project.title}' is active"

    elsif Project.active.count == 0
      puts "Activating '#{project.title}'"
      project.activate!

    else
      puts "____________"
      puts "Another project, '#{Project.active.first.title}', is currently active. To activate '#{project.title}', run:"
      puts "  rake project:activate[#{args[:project_key]}]"
    end
  end

  desc "List projects and active status"
  task :list, [] => :environment do |task, args|
    args.with_defaults area: 'all'

    puts "Listing projects:"
    Project.all.each do |project|
      puts "  [#{project.status == 'active' ? 'active' : ' ' * 6}] #{project.title}"
    end
  end

  desc "Activate a project by key. Only one project may be active at one time."
  task :activate, [:project_key] => :environment do |task, args|
    args.with_defaults area: 'all'

    project = get_project args[:project_key]
    if ! project.nil?
      puts "Activating #{project.title}"
      project.activate!
    end
  end

  def get_project(project_key)
    project = Project.find_by key: project_key
    puts "Failed to find project '#{project_key}'" if project.nil?
    project
  end

  def load_content(project_key)
    project_dir = Rails.root.join('project', project_key)
    project_file_path = "#{project_dir}/project.json"
    project_hash = JSON.parse File.read(project_file_path)

    # load project_file_path
    project = Project.find_or_create_by key: project_key

    # Establish some defaults so that if they're note set in the project hash, we save the default instead over any previous value:
    project_defaults = {
      background: nil,
      logo: nil,
      terms_map: {},
      team_emails: [],
      team: [],
      organizations: [],
      analytics: nil,
      forum: nil
    }
    # Set all valid fields from hash:
    project_hash = project_hash.inject(project_defaults) { |h, (k,v)| h[k] = v if Project.fields.keys.include?(k.to_s); h }
    project.update project_hash

    puts "Created project: #{project.title}"

    # Load pages from content/*:
    content_path = Rails.root.join('project', project_key, 'content')
    puts "Loading pages from #{content_path}:"

    prev_pages = project.pages
    project.pages = []

    Dir.foreach(content_path).each do |file|
      path = Rails.root.join content_path, file
      next if File.directory? path
      next if ! ['.html','.erb','.md'].include? path.extname
      ext = path.extname
{'fraction_non_alphanumeric': 0.12285257690771074, 'fraction_numerical': 0.00039952057530962844, 'mean_word_length': 3.0969721767594107, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6777526', 'n_tokens_mistral': 2992, 'n_tokens_neox': 2961, 'n_words': 922}