<commit_before>import { Subject, Observable } from 'rxjs'
import m from 'mithril'
import { catarse } from '../api'
import models from '../models'
import { ProjectDetails } from "../@types/project-details"
import h from '../h'
import { RailsErrors } from '../@types/rails-errors'
import _ from 'underscore'

const I18nScope = _.partial(h.i18nScope, 'activerecord.errors.models');

export class ProjectPublishByStepsVM {

    private _project : ProjectDetails | null
    private _projectSubject : Subject<ProjectDetails>
    private _isLoadingProject : boolean
    private _isSavingProject : boolean
    private _errors : { [key:string] : string[] }

    constructor(private project_id : number) {
        this._project = null
        this._isLoadingProject = true
        this._errors = {}
        this._projectSubject = new Subject<ProjectDetails>()
        this.init()
    }

    get projectObservable() : Observable<ProjectDetails> {
        return this._projectSubject
    }

    get project() : ProjectDetails {
        const self = this
        return {
            ...this._project,
            set headline(value) {
                self._project.headline = value
                self._projectSubject.next(self._project)
            },
            get headline() {
                return self._project.headline
            },
            set large_image(value) {
                self._project.large_image = value
                self._projectSubject.next(self._project)
            },
            get large_image() {
                return self._project.large_image
            },
            get video_url() {
                return self._project.video_url
            },
            set video_url(value) {
                self._project.video_url = value
            },
            get goal() {
                return self._project.goal
            },
            set goal(value) {
                self._project.goal = value
            },
            get about_html() {
                return self._project.about_html || ''
            },
            set about_html(value) {
                self._project.about_html = value
            },
            get permalink() {
                return self._project.permalink
            },
            set permalink(value) {
                self._project.permalink = value
            },
            get city_id() {
                return self._project.city_id
            },
            set city_id(value) {
                self._project.city_id = value
            }
        }
    }
    
    get isLoadingProject() : boolean {
        return this._isLoadingProject
    }

    get isSaving() : boolean {
        return this._isSavingProject
    }

    getErrors(field : string) : string[] {
        return this._errors[field] || []
    }

    hasErrorOn(field : string) : boolean {
        const errors = this._errors[field] || []
        return errors.length > 0
    }
    
    async save(fields : string[], requiredFields : string[], cardImageFile? : File | undefined) {
        try {
            this.clearErrors()
            this._isSavingProject = true

            h.redraw()
            let someInvalidation = false
            const projectHasImageUploaded = !this._project.large_image || !this._project.cover_image
            if (requiredFields.includes('uploaded_image') && projectHasImageUploaded) {
                someInvalidation = await this.uploadCardImage(cardImageFile)
            }
            const requiredFieldsWithoutUploadedImage = requiredFields.filter(rf => rf !== 'uploaded_image')
            return (await this.saveFields(fields, requiredFieldsWithoutUploadedImage)) && someInvalidation
        } catch(e) {
            return false
        } finally {
            this._isSavingProject = false
            h.redraw()
        }
    }

    private async saveFields(fields : string[], requiredFields : string[]) {
        
        this._isSavingProject = true
        
        h.redraw()

        const projectDataToSave = {}
        for (const field of fields) {<commit_msg>when already have image uploaded, don't require it to go to the next page<commit_after>import { Subject, Observable } from 'rxjs'
import m from 'mithril'
import { catarse } from '../api'
import models from '../models'
import { ProjectDetails } from "../@types/project-details"
import h from '../h'
import { RailsErrors } from '../@types/rails-errors'
import _ from 'underscore'

const I18nScope = _.partial(h.i18nScope, 'activerecord.errors.models');

export class ProjectPublishByStepsVM {

    private _project : ProjectDetails | null
    private _projectSubject : Subject<ProjectDetails>
    private _isLoadingProject : boolean
    private _isSavingProject : boolean
    private _errors : { [key:string] : string[] }

    constructor(private project_id : number) {
        this._project = null
        this._isLoadingProject = true
        this._errors = {}
        this._projectSubject = new Subject<ProjectDetails>()
        this.init()
    }

    get projectObservable() : Observable<ProjectDetails> {
        return this._projectSubject
    }

    get project() : ProjectDetails {
        const self = this
        return {
            ...this._project,
            set headline(value) {
                self._project.headline = value
                self._projectSubject.next(self._project)
            },
            get headline() {
                return self._project.headline
            },
            set large_image(value) {
                self._project.large_image = value
                self._projectSubject.next(self._project)
            },
            get large_image() {
                return self._project.large_image
            },
            get video_url() {
                return self._project.video_url
            },
            set video_url(value) {
                self._project.video_url = value
            },
            get goal() {
                return self._project.goal
            },
            set goal(value) {
                self._project.goal = value
            },
            get about_html() {
                return self._project.about_html || ''
            },
            set about_html(value) {
                self._project.about_html = value
            },
            get permalink() {
                return self._project.permalink
            },
            set permalink(value) {
                self._project.permalink = value
            },
            get city_id() {
                return self._project.city_id
            },
            set city_id(value) {
                self._project.city_id = value
            }
        }
    }
    
    get isLoadingProject() : boolean {
        return this._isLoadingProject
    }

    get isSaving() : boolean {
        return this._isSavingProject
    }

    getErrors(field : string) : string[] {
        return this._errors[field] || []
    }

    hasErrorOn(field : string) : boolean {
        const errors = this._errors[field] || []
        return errors.length > 0
    }
    
    async save(fields : string[], requiredFields : string[], cardImageFile? : File | undefined) {
        try {
            this.clearErrors()
            this._isSavingProject = true

            h.redraw()

            const projectHasImageUploaded = !!this._project.large_image || !!this._project.small_image || !!this._project.thumb_image
            let someInvalidation = projectHasImageUploaded

            if (requiredFields.includes('uploaded_image') && !projectHasImageUploaded) {
                someInvalidation = await this.uploadCardImage(cardImageFile)
            }
            const requiredFieldsWithoutUploadedImage = requiredFields.filter(rf => rf !== 'uploaded_image')
            return (await this.saveFields(fields, requiredFieldsWithoutUploadedImage)) && someInvalidation
        } catch(e) {
            return false
        } finally {
            this._isSavingProject = false
            h.redraw()
        }
    }

    private async saveFields(fields : string[], requiredFields : string[]) {
        
        this._isSavingProject = true
        
        h.redraw()

        const projectDataToSave = {}
        for (const field of fields) {
{'fraction_non_alphanumeric': 0.0942363813229572, 'fraction_numerical': 0.0012159533073929961, 'mean_word_length': 1.7199074074074074, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, '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': '5207826', 'n_tokens_mistral': 2136, 'n_tokens_neox': 2059, 'n_words': 458}