diff --git a/apps/fretonator-web/src/app/common/fret-map/fret-map.service.testConstants.ts b/apps/fretonator-web/src/app/common/fret-map/fret-map.service.testConstants.ts index df5e515..6deb8a8 100644 --- a/apps/fretonator-web/src/app/common/fret-map/fret-map.service.testConstants.ts +++ b/apps/fretonator-web/src/app/common/fret-map/fret-map.service.testConstants.ts @@ -1,4 +1,5 @@ import { ChordType, FretMap, ModeMap } from '../../util/types'; +import { ScaleDegrees } from '../../util/constants'; export const aSharpPentatonicMajor: ModeMap = [ { @@ -1037,159 +1038,159 @@ export const aSharpMajor: ModeMap = [ ]; export const cIonianFretMappings: FretMap = [ - { string: 'A', fret: 0, displayName: 'A', degree: 'submediant' }, - { string: 'A', fret: 2, displayName: 'B', degree: 'leadingTone' }, - { string: 'A', fret: 3, displayName: 'C', degree: 'tonic' }, - { string: 'A', fret: 5, displayName: 'D', degree: 'supertonic' }, - { string: 'A', fret: 7, displayName: 'E', degree: 'mediant' }, - { string: 'A', fret: 8, displayName: 'F', degree: 'subdominant' }, - { string: 'A', fret: 10, displayName: 'G', degree: 'dominant' }, - { string: 'A', fret: 12, displayName: 'A', degree: 'submediant' }, - { string: 'A', fret: 14, displayName: 'B', degree: 'leadingTone' }, - { string: 'A', fret: 15, displayName: 'C', degree: 'tonic' }, - { string: 'A', fret: 17, displayName: 'D', degree: 'supertonic' }, - { string: 'A', fret: 19, displayName: 'E', degree: 'mediant' }, - { string: 'A', fret: 20, displayName: 'F', degree: 'subdominant' }, - { string: 'A', fret: 22, displayName: 'G', degree: 'dominant' }, - { string: 'A', fret: 24, displayName: 'A', degree: 'submediant' }, - { string: 'B', fret: 0, displayName: 'B', degree: 'leadingTone' }, - { string: 'B', fret: 1, displayName: 'C', degree: 'tonic' }, - { string: 'B', fret: 3, displayName: 'D', degree: 'supertonic' }, - { string: 'B', fret: 5, displayName: 'E', degree: 'mediant' }, - { string: 'B', fret: 6, displayName: 'F', degree: 'subdominant' }, - { string: 'B', fret: 8, displayName: 'G', degree: 'dominant' }, - { string: 'B', fret: 10, displayName: 'A', degree: 'submediant' }, - { string: 'B', fret: 12, displayName: 'B', degree: 'leadingTone' }, - { string: 'B', fret: 13, displayName: 'C', degree: 'tonic' }, - { string: 'B', fret: 15, displayName: 'D', degree: 'supertonic' }, - { string: 'B', fret: 17, displayName: 'E', degree: 'mediant' }, - { string: 'B', fret: 18, displayName: 'F', degree: 'subdominant' }, - { string: 'B', fret: 20, displayName: 'G', degree: 'dominant' }, - { string: 'B', fret: 22, displayName: 'A', degree: 'submediant' }, - { string: 'B', fret: 24, displayName: 'B', degree: 'leadingTone' }, - { string: 'D', fret: 0, displayName: 'D', degree: 'supertonic' }, - { string: 'D', fret: 2, displayName: 'E', degree: 'mediant' }, - { string: 'D', fret: 3, displayName: 'F', degree: 'subdominant' }, - { string: 'D', fret: 5, displayName: 'G', degree: 'dominant' }, - { string: 'D', fret: 7, displayName: 'A', degree: 'submediant' }, - { string: 'D', fret: 9, displayName: 'B', degree: 'leadingTone' }, - { string: 'D', fret: 10, displayName: 'C', degree: 'tonic' }, - { string: 'D', fret: 12, displayName: 'D', degree: 'supertonic' }, - { string: 'D', fret: 14, displayName: 'E', degree: 'mediant' }, - { string: 'D', fret: 15, displayName: 'F', degree: 'subdominant' }, - { string: 'D', fret: 17, displayName: 'G', degree: 'dominant' }, - { string: 'D', fret: 19, displayName: 'A', degree: 'submediant' }, - { string: 'D', fret: 21, displayName: 'B', degree: 'leadingTone' }, - { string: 'D', fret: 22, displayName: 'C', degree: 'tonic' }, - { string: 'D', fret: 24, displayName: 'D', degree: 'supertonic' }, - { string: 'E', fret: 0, displayName: 'E', degree: 'mediant' }, - { string: 'E', fret: 1, displayName: 'F', degree: 'subdominant' }, - { string: 'E', fret: 3, displayName: 'G', degree: 'dominant' }, - { string: 'E', fret: 5, displayName: 'A', degree: 'submediant' }, - { string: 'E', fret: 7, displayName: 'B', degree: 'leadingTone' }, - { string: 'E', fret: 8, displayName: 'C', degree: 'tonic' }, - { string: 'E', fret: 10, displayName: 'D', degree: 'supertonic' }, - { string: 'E', fret: 12, displayName: 'E', degree: 'mediant' }, - { string: 'E', fret: 13, displayName: 'F', degree: 'subdominant' }, - { string: 'E', fret: 15, displayName: 'G', degree: 'dominant' }, - { string: 'E', fret: 17, displayName: 'A', degree: 'submediant' }, - { string: 'E', fret: 19, displayName: 'B', degree: 'leadingTone' }, - { string: 'E', fret: 20, displayName: 'C', degree: 'tonic' }, - { string: 'E', fret: 22, displayName: 'D', degree: 'supertonic' }, - { string: 'E', fret: 24, displayName: 'E', degree: 'mediant' }, - { string: 'G', fret: 0, displayName: 'G', degree: 'dominant' }, - { string: 'G', fret: 2, displayName: 'A', degree: 'submediant' }, - { string: 'G', fret: 4, displayName: 'B', degree: 'leadingTone' }, - { string: 'G', fret: 5, displayName: 'C', degree: 'tonic' }, - { string: 'G', fret: 7, displayName: 'D', degree: 'supertonic' }, - { string: 'G', fret: 9, displayName: 'E', degree: 'mediant' }, - { string: 'G', fret: 10, displayName: 'F', degree: 'subdominant' }, - { string: 'G', fret: 12, displayName: 'G', degree: 'dominant' }, - { string: 'G', fret: 14, displayName: 'A', degree: 'submediant' }, - { string: 'G', fret: 16, displayName: 'B', degree: 'leadingTone' }, - { string: 'G', fret: 17, displayName: 'C', degree: 'tonic' }, - { string: 'G', fret: 19, displayName: 'D', degree: 'supertonic' }, - { string: 'G', fret: 21, displayName: 'E', degree: 'mediant' }, - { string: 'G', fret: 22, displayName: 'F', degree: 'subdominant' }, - { string: 'G', fret: 24, displayName: 'G', degree: 'dominant' } + { string: 'A', fret: 0, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'A', fret: 2, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'A', fret: 3, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'A', fret: 5, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'A', fret: 7, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'A', fret: 8, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'A', fret: 10, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'A', fret: 12, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'A', fret: 14, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'A', fret: 15, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'A', fret: 17, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'A', fret: 19, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'A', fret: 20, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'A', fret: 22, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'A', fret: 24, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'B', fret: 0, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'B', fret: 1, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'B', fret: 3, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'B', fret: 5, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'B', fret: 6, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'B', fret: 8, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'B', fret: 10, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'B', fret: 12, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'B', fret: 13, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'B', fret: 15, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'B', fret: 17, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'B', fret: 18, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'B', fret: 20, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'B', fret: 22, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'B', fret: 24, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'D', fret: 0, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'D', fret: 2, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'D', fret: 3, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'D', fret: 5, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'D', fret: 7, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'D', fret: 9, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'D', fret: 10, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'D', fret: 12, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'D', fret: 14, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'D', fret: 15, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'D', fret: 17, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'D', fret: 19, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'D', fret: 21, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'D', fret: 22, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'D', fret: 24, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'E', fret: 0, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'E', fret: 1, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'E', fret: 3, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'E', fret: 5, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'E', fret: 7, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'E', fret: 8, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'E', fret: 10, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'E', fret: 12, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'E', fret: 13, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'E', fret: 15, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'E', fret: 17, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'E', fret: 19, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'E', fret: 20, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'E', fret: 22, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'E', fret: 24, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'G', fret: 0, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'G', fret: 2, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'G', fret: 4, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'G', fret: 5, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'G', fret: 7, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'G', fret: 9, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'G', fret: 10, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'G', fret: 12, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'G', fret: 14, displayName: 'A', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'G', fret: 16, displayName: 'B', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'G', fret: 17, displayName: 'C', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'G', fret: 19, displayName: 'D', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'G', fret: 21, displayName: 'E', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'G', fret: 22, displayName: 'F', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'G', fret: 24, displayName: 'G', degree: ScaleDegrees.dominant, degreeNumber: 5 } ]; export const dIonianFretMappings: FretMap = [ - { string: 'A', fret: 0, displayName: 'A', degree: 'dominant' }, - { string: 'A', fret: 2, displayName: 'B', degree: 'submediant' }, - { string: 'A', fret: 4, displayName: 'C#', degree: 'leadingTone' }, - { string: 'A', fret: 5, displayName: 'D', degree: 'tonic' }, - { string: 'A', fret: 7, displayName: 'E', degree: 'supertonic' }, - { string: 'A', fret: 9, displayName: 'F#', degree: 'mediant' }, - { string: 'A', fret: 10, displayName: 'G', degree: 'subdominant' }, - { string: 'A', fret: 12, displayName: 'A', degree: 'dominant' }, - { string: 'A', fret: 14, displayName: 'B', degree: 'submediant' }, - { string: 'A', fret: 16, displayName: 'C#', degree: 'leadingTone' }, - { string: 'A', fret: 17, displayName: 'D', degree: 'tonic' }, - { string: 'A', fret: 19, displayName: 'E', degree: 'supertonic' }, - { string: 'A', fret: 21, displayName: 'F#', degree: 'mediant' }, - { string: 'A', fret: 22, displayName: 'G', degree: 'subdominant' }, - { string: 'A', fret: 24, displayName: 'A', degree: 'dominant' }, - { string: 'B', fret: 0, displayName: 'B', degree: 'submediant' }, - { string: 'B', fret: 2, displayName: 'C#', degree: 'leadingTone' }, - { string: 'B', fret: 3, displayName: 'D', degree: 'tonic' }, - { string: 'B', fret: 5, displayName: 'E', degree: 'supertonic' }, - { string: 'B', fret: 7, displayName: 'F#', degree: 'mediant' }, - { string: 'B', fret: 8, displayName: 'G', degree: 'subdominant' }, - { string: 'B', fret: 10, displayName: 'A', degree: 'dominant' }, - { string: 'B', fret: 12, displayName: 'B', degree: 'submediant' }, - { string: 'B', fret: 14, displayName: 'C#', degree: 'leadingTone' }, - { string: 'B', fret: 15, displayName: 'D', degree: 'tonic' }, - { string: 'B', fret: 17, displayName: 'E', degree: 'supertonic' }, - { string: 'B', fret: 19, displayName: 'F#', degree: 'mediant' }, - { string: 'B', fret: 20, displayName: 'G', degree: 'subdominant' }, - { string: 'B', fret: 22, displayName: 'A', degree: 'dominant' }, - { string: 'B', fret: 24, displayName: 'B', degree: 'submediant' }, - { string: 'D', fret: 0, displayName: 'D', degree: 'tonic' }, - { string: 'D', fret: 2, displayName: 'E', degree: 'supertonic' }, - { string: 'D', fret: 4, displayName: 'F#', degree: 'mediant' }, - { string: 'D', fret: 5, displayName: 'G', degree: 'subdominant' }, - { string: 'D', fret: 7, displayName: 'A', degree: 'dominant' }, - { string: 'D', fret: 9, displayName: 'B', degree: 'submediant' }, - { string: 'D', fret: 11, displayName: 'C#', degree: 'leadingTone' }, - { string: 'D', fret: 12, displayName: 'D', degree: 'tonic' }, - { string: 'D', fret: 14, displayName: 'E', degree: 'supertonic' }, - { string: 'D', fret: 16, displayName: 'F#', degree: 'mediant' }, - { string: 'D', fret: 17, displayName: 'G', degree: 'subdominant' }, - { string: 'D', fret: 19, displayName: 'A', degree: 'dominant' }, - { string: 'D', fret: 21, displayName: 'B', degree: 'submediant' }, - { string: 'D', fret: 23, displayName: 'C#', degree: 'leadingTone' }, - { string: 'D', fret: 24, displayName: 'D', degree: 'tonic' }, - { string: 'E', fret: 0, displayName: 'E', degree: 'supertonic' }, - { string: 'E', fret: 2, displayName: 'F#', degree: 'mediant' }, - { string: 'E', fret: 3, displayName: 'G', degree: 'subdominant' }, - { string: 'E', fret: 5, displayName: 'A', degree: 'dominant' }, - { string: 'E', fret: 7, displayName: 'B', degree: 'submediant' }, - { string: 'E', fret: 9, displayName: 'C#', degree: 'leadingTone' }, - { string: 'E', fret: 10, displayName: 'D', degree: 'tonic' }, - { string: 'E', fret: 12, displayName: 'E', degree: 'supertonic' }, - { string: 'E', fret: 14, displayName: 'F#', degree: 'mediant' }, - { string: 'E', fret: 15, displayName: 'G', degree: 'subdominant' }, - { string: 'E', fret: 17, displayName: 'A', degree: 'dominant' }, - { string: 'E', fret: 19, displayName: 'B', degree: 'submediant' }, - { string: 'E', fret: 21, displayName: 'C#', degree: 'leadingTone' }, - { string: 'E', fret: 22, displayName: 'D', degree: 'tonic' }, - { string: 'E', fret: 24, displayName: 'E', degree: 'supertonic' }, - { string: 'G', fret: 0, displayName: 'G', degree: 'subdominant' }, - { string: 'G', fret: 2, displayName: 'A', degree: 'dominant' }, - { string: 'G', fret: 4, displayName: 'B', degree: 'submediant' }, - { string: 'G', fret: 6, displayName: 'C#', degree: 'leadingTone' }, - { string: 'G', fret: 7, displayName: 'D', degree: 'tonic' }, - { string: 'G', fret: 9, displayName: 'E', degree: 'supertonic' }, - { string: 'G', fret: 11, displayName: 'F#', degree: 'mediant' }, - { string: 'G', fret: 12, displayName: 'G', degree: 'subdominant' }, - { string: 'G', fret: 14, displayName: 'A', degree: 'dominant' }, - { string: 'G', fret: 16, displayName: 'B', degree: 'submediant' }, - { string: 'G', fret: 18, displayName: 'C#', degree: 'leadingTone' }, - { string: 'G', fret: 19, displayName: 'D', degree: 'tonic' }, - { string: 'G', fret: 21, displayName: 'E', degree: 'supertonic' }, - { string: 'G', fret: 23, displayName: 'F#', degree: 'mediant' }, - { string: 'G', fret: 24, displayName: 'G', degree: 'subdominant' } + { string: 'A', fret: 0, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'A', fret: 2, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'A', fret: 4, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'A', fret: 5, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'A', fret: 7, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'A', fret: 9, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'A', fret: 10, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'A', fret: 12, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'A', fret: 14, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'A', fret: 16, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'A', fret: 17, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'A', fret: 19, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'A', fret: 21, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'A', fret: 22, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'A', fret: 24, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'B', fret: 0, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'B', fret: 2, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'B', fret: 3, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'B', fret: 5, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'B', fret: 7, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'B', fret: 8, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'B', fret: 10, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'B', fret: 12, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'B', fret: 14, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'B', fret: 15, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'B', fret: 17, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'B', fret: 19, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'B', fret: 20, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'B', fret: 22, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'B', fret: 24, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'D', fret: 0, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'D', fret: 2, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'D', fret: 4, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'D', fret: 5, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'D', fret: 7, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'D', fret: 9, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'D', fret: 11, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'D', fret: 12, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'D', fret: 14, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'D', fret: 16, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'D', fret: 17, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'D', fret: 19, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'D', fret: 21, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'D', fret: 23, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'D', fret: 24, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'E', fret: 0, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'E', fret: 2, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'E', fret: 3, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'E', fret: 5, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'E', fret: 7, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'E', fret: 9, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'E', fret: 10, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'E', fret: 12, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'E', fret: 14, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'E', fret: 15, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'E', fret: 17, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'E', fret: 19, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'E', fret: 21, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'E', fret: 22, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'E', fret: 24, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'G', fret: 0, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'G', fret: 2, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'G', fret: 4, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'G', fret: 6, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'G', fret: 7, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'G', fret: 9, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'G', fret: 11, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'G', fret: 12, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 }, + { string: 'G', fret: 14, displayName: 'A', degree: ScaleDegrees.dominant, degreeNumber: 5 }, + { string: 'G', fret: 16, displayName: 'B', degree: ScaleDegrees.submediant, degreeNumber: 6 }, + { string: 'G', fret: 18, displayName: 'C#', degree: ScaleDegrees.leadingTone, degreeNumber: 7 }, + { string: 'G', fret: 19, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }, + { string: 'G', fret: 21, displayName: 'E', degree: ScaleDegrees.supertonic, degreeNumber: 2 }, + { string: 'G', fret: 23, displayName: 'F#', degree: ScaleDegrees.mediant, degreeNumber: 3 }, + { string: 'G', fret: 24, displayName: 'G', degree: ScaleDegrees.subdominant, degreeNumber: 4 } ]; export const cMajorPentatonicChordMap = [ diff --git a/apps/fretonator-web/src/app/common/fret-map/fret-map.service.ts b/apps/fretonator-web/src/app/common/fret-map/fret-map.service.ts index a8cc290..3b53df5 100644 --- a/apps/fretonator-web/src/app/common/fret-map/fret-map.service.ts +++ b/apps/fretonator-web/src/app/common/fret-map/fret-map.service.ts @@ -17,7 +17,7 @@ import { ModeSelectorObjects, NoteToStringAndFretMap, Octave, - ScaleDegrees, + ScaleDegreeNames, StandardModePatterns } from '../../util/constants'; import { JamTracksData } from '../../data/jamTracks'; @@ -330,16 +330,17 @@ export class FretMapService { const modeMap = origModeMap.map((noteObject, index) => ({ ...noteObject, - degree: ScaleDegrees[index] + degree: ScaleDegreeNames[index], })); return modeMap - .map((note) => + .map((note, index) => NoteToStringAndFretMap[this.convertNoteToFretMapKey(note)] .map((thisNote: NoteObject) => ({ ...thisNote, displayName: note.displayName, - degree: note.degree + degree: note.degree, + degreeNumber: index + 1 }))) .flat() .reduce((acc, curr) => [...acc, curr], []) diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.html b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.html new file mode 100644 index 0000000..67e6db1 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.html @@ -0,0 +1,24 @@ +
+
+ + +
+
+ + +
+
diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.scss b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.scss new file mode 100644 index 0000000..725d12b --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.scss @@ -0,0 +1,47 @@ +@import "../../../../styles/vars"; +@import "../../../../styles/functions"; +@import "../../../../styles/mixins"; +@import "../../../../styles/typography"; + +.configure__controls { + display: flex; + flex-direction: column; +} + +.button__group { + display: flex; + flex-direction: row; + justify-content: center; + margin-bottom: pxToRem($grid-unit * 2); + + &:last-of-type { + margin-bottom: 0; + } + + @media screen and (min-width: $screen-med) { + justify-content: flex-end; + } +} + +.fretboard__toggleButton { + @include chip_button_base(); + padding: pxToRem($grid-unit * 1.5); + border-color: var(--fretboard-toggle-button-border-color); +} + +.fretboard__toggleButton--active { + background-color: var(--chip-background-color-active); + color: var(--chip-foreground-color-active); +} + +.fretboard__toggleButton:first-of-type { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right-width: calc(var(--border-width-button) / 2); +} + +.fretboard__toggleButton:last-of-type { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left-width: calc(var(--border-width-button) / 2); +} diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.spec.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.spec.ts new file mode 100644 index 0000000..f383963 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.spec.ts @@ -0,0 +1,36 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { FretboardConfigComponent } from './fretboard-config.component'; +import { Component } from '@angular/core'; +import { FretboardConfigModule } from './fretboard-config.module'; + +describe('FretboardConfigComponent', () => { + @Component({ + selector: 'app-fretboard-config-spec', + template: ` + + ` + }) + class FretboardConfigComponentSpec { + } + + let component: FretboardConfigComponentSpec; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FretboardConfigComponentSpec ], + imports: [FretboardConfigModule] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FretboardConfigComponentSpec); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.ts new file mode 100644 index 0000000..9bcb915 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.component.ts @@ -0,0 +1,31 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { FretModes, Orientations } from '../fretboard/fretboard.component'; + +@Component({ + selector: 'app-fretboard-config', + templateUrl: './fretboard-config.component.html', + styleUrls: ['./fretboard-config.component.scss'] +}) +export class FretboardConfigComponent { + @Input() fretMode; + @Input() orientation; + + @Output() setFretMode = new EventEmitter(); + @Output() setOrientation = new EventEmitter(); + + setFretModeClick(fretMode: FretModes) { + this.setFretMode.emit(fretMode); + } + + setOrientationClick(orientation: Orientations) { + this.setOrientation.emit(orientation); + } + + get FretModes() { + return FretModes; + } + + get Orientations() { + return Orientations; + } +} diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.module.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.module.ts new file mode 100644 index 0000000..8be8ee8 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard-config/fretboard-config.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FretboardConfigComponent } from './fretboard-config.component'; + + +@NgModule({ + declarations: [FretboardConfigComponent], + exports: [ + FretboardConfigComponent + ], + imports: [ + CommonModule + ], +}) +export class FretboardConfigModule { +} diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.html b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.html index 59d0251..cc71fc6 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.html +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.html @@ -9,8 +9,9 @@ [attr.data-string]="string" [attr.data-fret]="fret" [attr.data-degree]="(fretMap | getFretFromFretMap: stringName:fret:stringNamesAreCaseSensitive)?.degree" - [attr.data-display-note]="(fretMap | getFretFromFretMap: stringName:fret:stringNamesAreCaseSensitive)?.displayName" + [attr.data-display-note]="noteNameDisplay === NoteDisplays.noteNames ? ((fretMap | getFretFromFretMap: stringName:fret:stringNamesAreCaseSensitive)?.displayName) : ((fretMap | getFretFromFretMap: stringName:fret:stringNamesAreCaseSensitive)?.degreeNumber)" [attr.data-mode]="mode" + [attr.data-highlight]="highlightedDegrees.has((fretMap | getFretFromFretMap: stringName:fret:stringNamesAreCaseSensitive)?.degree)" (click)="playbackService.playNote(stringName, fret)" > @@ -22,42 +23,18 @@ -
- - - - -
-
+ [class.fretboard__flip]="orientation === Orientations.left">
- + [class.fretboard__flip]="orientation === Orientations.left" + [class.fretboard__wide]="fretMode === FretModes.twentyFour">
+ [class.fretboard__leftHanded]="orientation === Orientations.left" + [class.fretboard__24]="fretMode === FretModes.twentyFour"> -
-
+ [class.fretboard__leftHanded]="orientation === Orientations.left" + [class.fretboard__24]="fretMode === FretModes.twentyFour">
-

- - - - Tap notes on the fretboard for sound! -

+
+
+ Configure scale degrees + Highlight scale degrees + + +
+ + +
+
+ +
+ Configure fretboard + +
+
diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.scss b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.scss index 99f64bd..6fd2932 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.scss +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.scss @@ -30,7 +30,7 @@ $note-height: 36; .fretboard__help { text-align: center; - padding-top: pxToRem($grid-unit * 4); + padding-top: pxToRem($grid-unit * 2); &[data-fret="3"], &[data-fret="5"], @@ -306,21 +306,21 @@ $note-height: 36; } } - &[data-degree="tonic"] { + &[data-degree="tonic"][data-highlight="true"] { &:after { background-color: var(--note-bg-tonic); color: var(--note-color-tonic); } } - &[data-degree="mediant"] { + &[data-degree="mediant"][data-highlight="true"] { &:after { background-color: var(--note-bg-mediant); color: var(--note-color-mediant); } } - &[data-degree="dominant"] { + &[data-degree="dominant"][data-highlight="true"] { &:after { background-color: var(--note-bg-dominant); color: var(--note-color-dominant); @@ -342,7 +342,7 @@ $note-height: 36; &:after { content: attr(data-string-name); height: pxToRem($note-height); - width: pxToRem($note-height); + width: pxToRem($note-height); left: 0; right: unset; box-sizing: border-box; @@ -379,21 +379,21 @@ $note-height: 36; } } - &[data-degree="tonic"] { + &[data-degree="tonic"][data-highlight="true"] { &:after { background-color: var(--note-bg-tonic); color: var(--note-color-tonic); } } - &[data-degree="mediant"] { + &[data-degree="mediant"][data-highlight="true"] { &:after { background-color: var(--note-bg-mediant); color: var(--note-color-mediant); } } - &[data-degree="dominant"] { + &[data-degree="dominant"][data-highlight="true"] { &:after { background-color: var(--note-bg-dominant); color: var(--note-color-dominant); @@ -407,7 +407,7 @@ $note-height: 36; display: block; margin-top: pxToRem($grid-unit * 4); - @media screen and (min-width: 712px) { + @media screen and (min-width: 1324px) { display: none; } } @@ -421,7 +421,7 @@ $note-height: 36; &:before, &:after { - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 512 512'%3E%3Cpath fill='%233993dd' d='M319.1 217c20.2 20.2 19.9 53.2-.6 73.7s-53.5 20.8-73.7.6l-190-190c-20.1-20.2-19.8-53.2.7-73.7S109 6.8 129.1 27l190 190z'/%3E%3Cpath fill='%233993dd' d='M319.1 290.5c20.2-20.2 19.9-53.2-.6-73.7s-53.5-20.8-73.7-.6l-190 190c-20.2 20.2-19.9 53.2.6 73.7s53.5 20.8 73.7.6l190-190z'/%3E%3C/svg%3E"); + content: var(--fretboard-arrow-svg); } @@ -449,66 +449,6 @@ $note-height: 36; } } -.fretboard__toggle { - display: block; - text-align: center; - margin: pxToRem($grid-unit * 2) auto 0 auto; -} - -.fretboard__toggleButton { - @include chip_button_base(); - height: pxToRem(44); -} - -.toggle__shortLabel { - display: inline; - font-weight: inherit; - padding-left: pxToRem($grid_unit * 1.5); - padding-right: pxToRem($grid_unit * 1.5); - - @media screen and (min-width: $screen-med) { - display: none; - } -} - -.toggle__longLabel { - display: none; - font-weight: inherit; - - @media screen and (min-width: $screen-med) { - display: inline; - } -} - -.fretboard__toggleButton--active { - background-color: var(--chip-background-color-active); - color: var(--chip-foreground-color-active); -} - -.fretboard__toggleButton--left { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - border-right-width: calc(var(--border-width-button) / 2); -} - -.fretboard__toggleButton--middle-left { - border-radius: 0; - border-right-width: calc(var(--border-width-button) / 2); - border-left-width: 0; -} - -.fretboard__toggleButton--middle-right { - border-radius: 0; - border-right-width: 0; - border-left-width: calc(var(--border-width-button) / 2); -} - -.fretboard__toggleButton--right { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-left-width: calc(var(--border-width-button) / 2); -} - .fretonator__playCtaIcon { display: flex; height: pxToRem($grid-unit * 2); @@ -541,3 +481,91 @@ $note-height: 36; } } } + +.controlPanel { + @include content_wrapper(); + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + max-width: $screen-med; + margin-top: pxToRem($grid-unit * 2); + margin-bottom: pxToRem($grid-unit * 2); + background-color: var(--background-color-light); + padding: pxToRem($grid-unit * 4); + border-radius: pxToRem($grid-unit * 4); + box-shadow: 0 pxToRem(1) pxToRem(3) rgba(26, 26, 26, 0.12), 0 pxToRem(1) pxToRem(2) rgba(26, 26, 26, 0.24); + + @media screen and (min-width: $screen-med) { + flex-direction: row; + } +} + +.controlPanel__section { + display: flex; + flex-direction: column; + width: 100%; + margin-bottom: pxToRem($grid-unit * 4); + + &:last-of-type { + margin-bottom: 0; + } + + @media screen and (min-width: $screen-med) { + margin-bottom: 0; + } +} + +.controlPanel__title { + @include info_container_title; + text-align: center; + + @media screen and (min-width: $screen-med) { + text-align: left; + } +} + +.controlPanel__title--right { + text-align: center; + @media screen and (min-width: $screen-med) { + text-align: right; + } +} + +.button__group { + display: flex; + flex-direction: row; + justify-content: center; + margin-bottom: pxToRem($grid-unit * 2); + + &:last-of-type { + margin-bottom: 0; + } + + @media screen and (min-width: $screen-med) { + justify-content: flex-start; + } +} + +.fretboard__toggleButton { + @include chip_button_base(); + padding: pxToRem($grid-unit * 1.5); + border-color: var(--fretboard-toggle-button-border-color); +} + +.fretboard__toggleButton--active { + background-color: var(--chip-background-color-active); + color: var(--chip-foreground-color-active); +} + +.fretboard__toggleButton:first-of-type { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right-width: calc(var(--border-width-button) / 2); +} + +.fretboard__toggleButton:last-of-type { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left-width: calc(var(--border-width-button) / 2); +} diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.spec.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.spec.ts index ac6550c..5f93121 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.spec.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.spec.ts @@ -7,10 +7,10 @@ import { By } from '@angular/platform-browser'; describe('FretboardComponent', () => { const selectors = { - twelveButton: By.css('.fretboard__toggleButton--left'), - twentyFourButton: By.css('.fretboard__toggleButton--middle-left'), - rightButton: By.css('.fretboard__toggleButton--right'), - leftButton: By.css('.fretboard__toggleButton--middle-right') + twelveButton: By.css('.fretboard__toggleButton.twelve'), + twentyFourButton: By.css('.fretboard__toggleButton.twentyFour'), + rightButton: By.css('.fretboard__toggleButton.right'), + leftButton: By.css('.fretboard__toggleButton.left') }; const classNames = { @@ -91,5 +91,5 @@ describe('FretboardComponent', () => { fixture.detectChanges(); expect(rightButton.classes[classNames.toggleFretButtonSelected]).toBeTruthy(); }); - }) + }); }); diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.ts index 0dcfd54..9a479e7 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.component.ts @@ -2,17 +2,23 @@ import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, import { FretMap, Mode } from '../../../util/types'; import { NotePlaybackService } from '../../playback/note-playback.service'; import { AbstractDataService } from '../../abstract-data/abstract-data.service'; +import { ScaleDegrees } from '../../../util/constants'; -export enum FretMode { +export enum FretModes { twelve = 'twelve', twentyFour = 'twentyFour', } -export enum Orientation { +export enum Orientations { left = 'left', right = 'right', } +export enum NoteDisplays { + numbers = 'numbers', + noteNames = 'noteNames' +} + const FretReturner = { 'twelve': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 'twentyFour': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] @@ -20,8 +26,9 @@ const FretReturner = { const StorageKeys = { fretMode: 'fretonator_fretMode', - orientation: 'fretonator_orientation' -} + orientation: 'fretonator_orientation', + noteNameDisplay: 'fretonator_noteNameDisplay' +}; @Component({ selector: 'app-fretboard', @@ -39,69 +46,72 @@ export class FretboardComponent implements OnChanges, OnInit { orientation; fretMode; frets; + highlightedDegrees = new Set(); + noteNameDisplay = NoteDisplays.noteNames; constructor(public playbackService: NotePlaybackService, private localStorage: AbstractDataService) { } ngOnInit() { - const _fretMode = this.localStorage.getItem(StorageKeys.fretMode); - switch (_fretMode) { - case 'twelve': - this.fretMode = FretMode.twelve; - break; - case 'twentyFour': - this.fretMode = FretMode.twentyFour; - break; - default: - this.fretMode = FretMode.twelve; - } - - const _orientation = this.localStorage.getItem(StorageKeys.orientation); - switch (_orientation) { - case 'right': - this.orientation = Orientation.right; - break; - case 'left': - this.orientation = Orientation.left; - break; - default: - this.orientation = Orientation.right; - } + this.loadPropFromStorage(StorageKeys.fretMode, 'fretMode', FretModes.twelve); + this.loadPropFromStorage(StorageKeys.orientation, 'orientation', Orientations.right); + this.loadPropFromStorage(StorageKeys.noteNameDisplay, 'noteNameDisplay', NoteDisplays.noteNames); + this.toggleHighlight(ScaleDegrees.tonic); this.configureFretboard(); } - ngOnChanges(): void { if (this.loadExpanded) { - this.setFretMode(FretMode.twentyFour); + this.setFretMode(FretModes.twentyFour); } } - get fretModes() { - return FretMode; + get FretModes() { + return FretModes; + } + + get Orientations() { + return Orientations; } - get orientations() { - return Orientation; + get ScaleDegrees() { + return ScaleDegrees; + } + + get NoteDisplays() { + return NoteDisplays; } configureFretboard() { this.frets = FretReturner[this.fretMode]; - this.loadExpandedChange.emit(this.fretMode === FretMode.twentyFour); + this.loadExpandedChange.emit(this.fretMode === FretModes.twentyFour); } - setOrientation(orientation: Orientation) { + setOrientation(orientation: Orientations) { this.orientation = orientation; this.localStorage.setItem(StorageKeys.orientation, this.orientation); - this.configureFretboard(); } - setFretMode(fretMode: FretMode) { + setFretMode(fretMode: FretModes) { this.fretMode = fretMode; this.localStorage.setItem(StorageKeys.fretMode, this.fretMode); this.configureFretboard(); } + + toggleHighlight(degree: ScaleDegrees) { + this.highlightedDegrees.has(degree) ? this.highlightedDegrees.delete(degree) : this.highlightedDegrees.add(degree); + } + + toggleNoteDisplay(displayType: NoteDisplays) { + this.noteNameDisplay = displayType; + this.localStorage.setItem(StorageKeys.noteNameDisplay, displayType); + } + + loadPropFromStorage(storageKey: string, propName: string, defaultValue: T) { + const value = this.localStorage.getItem(storageKey); + this[propName] = value || defaultValue; + } } diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.module.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.module.ts index 3fe1197..eb69123 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.module.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard/fretboard.module.ts @@ -3,16 +3,22 @@ import { CommonModule } from '@angular/common'; import { FretboardComponent } from './fretboard.component'; import { GetFretFromFretMapPipe } from './get-fret-from-fret-map.pipe'; import { SpeakerModule } from '../../svgs/speaker/speaker.module'; +import { ScaleDegreesModule } from '../scale-degrees/scale-degrees.module'; +import { FretboardConfigModule } from '../fretboard-config/fretboard-config.module'; +import { ScaleMapModule } from '../scale-map/scale-map.module'; @NgModule({ declarations: [ FretboardComponent, - GetFretFromFretMapPipe + GetFretFromFretMapPipe, ], imports: [ CommonModule, - SpeakerModule + SpeakerModule, + ScaleDegreesModule, + FretboardConfigModule, + ScaleMapModule ], exports: [ FretboardComponent diff --git a/apps/fretonator-web/src/app/common/fretonator/fretboard/get-fret-from-fret-map.pipe.spec.ts b/apps/fretonator-web/src/app/common/fretonator/fretboard/get-fret-from-fret-map.pipe.spec.ts index 76d52ab..e7ba189 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretboard/get-fret-from-fret-map.pipe.spec.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretboard/get-fret-from-fret-map.pipe.spec.ts @@ -1,4 +1,5 @@ import { GetFretFromFretMapPipe } from './get-fret-from-fret-map.pipe'; +import { ScaleDegrees } from '../../../util/constants'; describe('GetNoteFromFretMapPipe', () => { it('create an instance', () => { @@ -9,7 +10,7 @@ describe('GetNoteFromFretMapPipe', () => { it('returns a truthy value if the note is found in the fret map', () => { const pipe = new GetFretFromFretMapPipe(); const result = pipe.transform( - [{ string: 'A', fret: 5, displayName: 'D', degree: 'tonic' }], + [{ string: 'A', fret: 5, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }], 'A', 5, false, @@ -21,7 +22,7 @@ describe('GetNoteFromFretMapPipe', () => { it('returns false if the note is not found in the fret map', () => { const pipe = new GetFretFromFretMapPipe(); const result = pipe.transform( - [{ string: 'A', fret: 5, displayName: 'D', degree: 'tonic' }], + [{ string: 'A', fret: 5, displayName: 'D', degree: ScaleDegrees.tonic, degreeNumber: 1 }], 'B', 5, false, @@ -34,7 +35,7 @@ describe('GetNoteFromFretMapPipe', () => { fit('deals with case sensitivity', () => { const pipe = new GetFretFromFretMapPipe(); const result = pipe.transform( - [{ string: 'E', fret: 5, displayName: 'A', degree: 'tonic' }], + [{ string: 'E', fret: 5, displayName: 'A', degree: ScaleDegrees.tonic, degreeNumber: 1 }], 'e', 5, true, diff --git a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.html b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.html index 2b483ac..b1f9a2c 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.html +++ b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.html @@ -3,14 +3,6 @@

Check out the fretboard

- - @@ -25,6 +17,87 @@

Learn the theory

[note]="note" [noteExtenderString]="noteExtenderString"> +
+ + + + Break modes down into patterns + + + + +
+ +
+

About Scale Degrees + +

+

+ Each of the 7 notes of a mode or scale is called a scale degree, and has a specific name. +

+
    +
  1. Tonic
  2. +
  3. Supertonic
  4. +
  5. Mediant
  6. +
  7. Subdominant
  8. +
  9. Dominant
  10. +
  11. Submediant
  12. +
  13. Leading note
  14. +
+

+ Notes 1, 3 and 5 of a scale make up the tonic triad, which is simply a chord of three notes built on + the first note of the scale. This is the the most important chord to learn when jamming as it is the home + chord - meaning it's usually the chord that the jam track starts on and returns to often. +

+

+ Scale degrees 1, 3, and 5 can be highlighted on the fretboard to give you a helpful point of reference when + learning + the mode. +

+
+ +
+

About Theoretical Scales + +

+

A theoretical scale or impossible key is a key whose key signature has at least + one double flat (𝄫) or double sharp (x).

+

{{modeDisplayString}} is a theoretical scale and looks unnecessarily complicated. We can + make things simpler!

+

Switch to the enharmonic equivalent note + of {{modeMap[0].displayName | getEnharmonicEquivalent }} to make + the notes easier to read. (It'll sound exactly the same!)

+ Switch to {{modeMap[0].displayName | getEnharmonicEquivalent }} +
+ @@ -33,5 +106,4 @@

Learn the theory

[similarModes]="modeMap | getSimilarModes : mode" [isTheoretical]="modeMap | isTheoreticalScale"> - diff --git a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.scss b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.scss index 5907165..2fe5bac 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.scss +++ b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.scss @@ -19,14 +19,96 @@ text-align: center; } -.cta__row { - text-align: center; - padding-top: pxToRem($grid-unit * 4); +.infoButtonRow { + display: flex; + flex-direction: column; + margin-top: pxToRem($grid-unit * 4); + margin-bottom: pxToRem($grid-unit * 8); + justify-content: space-between; + + @media screen and (min-width: $screen-med) { + flex-direction: row; + } +} + +.infoButton { + @include chip_button_base(); + border-color: var(--fretboard-toggle-button-border-color); + margin-bottom: pxToRem($grid-unit * 2); + height: pxToRem(44); + justify-content: space-between; + align-content: center; + + @media screen and (min-width: $screen-med) { + margin-bottom: 0; + height: unset; + } +} + +.infoButton--withChevron { + display: flex; + justify-content: center; + align-items: center; + line-height: 1; +} + +.infoButton__svgContainer { + height: pxToRem($grid-unit * 1.5); + display: inline-block; + margin-left: pxToRem($grid-unit / 2); +} + +.infoBlock { + background-color: var(--black); + margin: pxToRem($grid-unit * 4) pxToRem($grid-unit * -4); + padding: pxToRem($grid-unit * 4); + display: flex; + flex-direction: column; } -.learnHub__cta { - @include text_link; - margin-left: auto; - margin-right: auto; - line-height: pxToRem(30); +.infoBlock__title { + @include font_medium; + color: var(--peach); + padding-bottom: pxToRem($grid-unit * 2); + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; } + +.infoBlock__close { + border-width: 0; + background-color: transparent; + height: pxToRem(44); + width: pxToRem(44); + padding: pxToRem($grid-unit); + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + color: var(--grey); +} + +.infoBlock__copy { + @include font_bodyCopy; + color: var(--offwhite); + margin-top: pxToRem($grid-unit * 2); + margin-bottom: pxToRem($grid-unit * 2); +} + +.infoBlock__list { + +} + +.infoBlock__listItem { + @include font_bodyCopy; + color: var(--yellow); + margin-bottom: pxToRem($grid-unit * 1); +} + +.actionButton { + @include hard_button_base(); + margin-bottom: pxToRem($grid-unit * 2); + align-self: flex-start; +} + diff --git a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.spec.ts b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.spec.ts index f20e930..c2b3866 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.spec.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.spec.ts @@ -2,10 +2,16 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { FretonatorComponent } from './fretonator.component'; import { FretonatorModule } from './fretonator.module'; -import { Component } from '@angular/core'; +import { Component, DebugElement } from '@angular/core'; import { RouterTestingModule } from '@angular/router/testing'; +import { By } from '@angular/platform-browser'; describe('FretonatorComponent', () => { + const selectors = { + toggleScaleInfo: By.css('.infoButton--scaleMapInfo'), + scaleMapDegreesInfo: By.css('.infoBlock--scaleDegrees'), + }; + @Component({ selector: 'app-fretonator-spec', template: ` @@ -46,4 +52,22 @@ describe('FretonatorComponent', () => { expect(component).toBeTruthy(); expect(component).toMatchSnapshot(); }); + + describe('toggleScaleMapInfo()', () => { + let toggleScaleButton: DebugElement; + + beforeEach(() => { + toggleScaleButton = fixture.debugElement.query(selectors.toggleScaleInfo); + toggleScaleButton.nativeElement.click(); + fixture.detectChanges(); + }); + + it('should show the scale map info', () => { + expect(fixture.debugElement.query(selectors.scaleMapDegreesInfo)).toBeTruthy(); + }); + + it('should update the text on the toggle button', () => { + expect(toggleScaleButton.nativeElement.textContent.trim()).toBe('Hide scale degrees info'); + }); + }); }); diff --git a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.ts b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.ts index 53db103..d8c2a69 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretonator.component.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretonator.component.ts @@ -1,6 +1,16 @@ import { Component, Input } from '@angular/core'; import { ChordMap, FretMap, Mode, ModeMap } from '../../util/types'; +import { GlobalService } from '../../global.service'; +enum ScaleDegreesToggleText { + hidden = 'About scale degrees', + visible = 'Hide scale degrees info' +} + +enum TheoreticalScalesToggleText { + hidden = 'About theoretical scales', + visible = 'Hide theoretical info' +} @Component({ selector: 'app-fretonator', @@ -17,4 +27,26 @@ export class FretonatorComponent { @Input() note: string; @Input() noteExtenderString: string; @Input() noteExtender: string; + showScaleMapInfo = false; + scaleDegreesToggleText = ScaleDegreesToggleText.hidden; + showTheoreticalScalesInfo = false; + theoreticalScalesToggleText = TheoreticalScalesToggleText.hidden; + + constructor(private globalService: GlobalService) { + } + + toggleScaleMapInfo() { + this.showScaleMapInfo = !this.showScaleMapInfo; + this.scaleDegreesToggleText = this.showScaleMapInfo ? ScaleDegreesToggleText.visible : ScaleDegreesToggleText.hidden; + } + + toggleTheoreticalScaleInfo() { + this.showTheoreticalScalesInfo = !this.showTheoreticalScalesInfo; + this.theoreticalScalesToggleText = this.showTheoreticalScalesInfo ? TheoreticalScalesToggleText.visible : TheoreticalScalesToggleText.hidden; + } + + enharmonicLinkClick() { + this.toggleTheoreticalScaleInfo(); + this.globalService.getScrollTarget().scrollIntoView(); + } } diff --git a/apps/fretonator-web/src/app/common/fretonator/fretonator.module.ts b/apps/fretonator-web/src/app/common/fretonator/fretonator.module.ts index bbcd8a4..37daaf2 100644 --- a/apps/fretonator-web/src/app/common/fretonator/fretonator.module.ts +++ b/apps/fretonator-web/src/app/common/fretonator/fretonator.module.ts @@ -12,6 +12,10 @@ import { SymbolToNoteObjPipe } from './symbol-to-note-obj.pipe'; import { GetJamTrackPipe } from './get-jam-track.pipe'; import { FretboardModule } from './fretboard/fretboard.module'; import { RouterModule } from '@angular/router'; +import { CrossModule } from '../svgs/cross/cross.module'; +import { GetEnharmonicEquivalentPipe } from './get-enharmonic-equivalent.pipe'; +import { GetEnharmonicRouterLinkPipe } from './get-enharmonic-router-link.pipe'; +import { ChevronRightModule } from '../svgs/chevron-right/chevron-right.module'; @NgModule({ declarations: [ @@ -20,6 +24,8 @@ import { RouterModule } from '@angular/router'; GetSimilarModesPipe, SymbolToNoteObjPipe, GetJamTrackPipe, + GetEnharmonicEquivalentPipe, + GetEnharmonicRouterLinkPipe ], imports: [ CommonModule, @@ -29,10 +35,12 @@ import { RouterModule } from '@angular/router'; SimilarModesModule, VideoLoaderModule, FretboardModule, - RouterModule + RouterModule, + CrossModule, + ChevronRightModule ], exports: [ - FretonatorComponent + FretonatorComponent, ] }) export class FretonatorModule { diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-equivalent.pipe.spec.ts b/apps/fretonator-web/src/app/common/fretonator/get-enharmonic-equivalent.pipe.spec.ts similarity index 100% rename from apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-equivalent.pipe.spec.ts rename to apps/fretonator-web/src/app/common/fretonator/get-enharmonic-equivalent.pipe.spec.ts diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-equivalent.pipe.ts b/apps/fretonator-web/src/app/common/fretonator/get-enharmonic-equivalent.pipe.ts similarity index 87% rename from apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-equivalent.pipe.ts rename to apps/fretonator-web/src/app/common/fretonator/get-enharmonic-equivalent.pipe.ts index 9fc3b22..2c5e59f 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-equivalent.pipe.ts +++ b/apps/fretonator-web/src/app/common/fretonator/get-enharmonic-equivalent.pipe.ts @@ -1,5 +1,5 @@ import { Pipe, PipeTransform } from '@angular/core'; -import { Enharmonics } from '../../../util/constants'; +import { Enharmonics } from '../../util/constants'; @Pipe({ name: 'getEnharmonicEquivalent' diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-router-link.pipe.spec.ts b/apps/fretonator-web/src/app/common/fretonator/get-enharmonic-router-link.pipe.spec.ts similarity index 100% rename from apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-router-link.pipe.spec.ts rename to apps/fretonator-web/src/app/common/fretonator/get-enharmonic-router-link.pipe.spec.ts diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-router-link.pipe.ts b/apps/fretonator-web/src/app/common/fretonator/get-enharmonic-router-link.pipe.ts similarity index 93% rename from apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-router-link.pipe.ts rename to apps/fretonator-web/src/app/common/fretonator/get-enharmonic-router-link.pipe.ts index c58992f..2794dd8 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/get-enharmonic-router-link.pipe.ts +++ b/apps/fretonator-web/src/app/common/fretonator/get-enharmonic-router-link.pipe.ts @@ -1,5 +1,5 @@ import { Pipe, PipeTransform } from '@angular/core'; -import { Enharmonics } from '../../../util/constants'; +import { Enharmonics } from '../../util/constants'; @Pipe({ name: 'getEnharmonicRouterLink' diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.html b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.html new file mode 100644 index 0000000..bd5844e --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.html @@ -0,0 +1,20 @@ +
+ + + +
diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.scss b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.scss new file mode 100644 index 0000000..2173412 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.scss @@ -0,0 +1,58 @@ +@import "../../../../styles/vars"; +@import "../../../../styles/functions"; +@import "../../../../styles/mixins"; +@import "../../../../styles/typography"; + +.degreesDisplay { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin-bottom: pxToRem($grid-unit * 2); + + @media screen and (min-width: $screen-med) { + justify-content: flex-start; + height: pxToRem(46); + } +} + +.degreesDisplay__degree { + display: flex; + justify-content: center; + align-items: center; + font-size: pxToRem(16); + height: pxToRem($grid-unit * 4); + width: pxToRem($grid-unit * 4); + border-radius: 50%; + font-weight: var(--font-weight-bold); + font-family: var(--font-family-main); + margin-left: pxToRem($grid-unit); + margin-right: pxToRem($grid-unit); + cursor: pointer; + background-color: var(--note-background); + color: var(--note-color); + border-width: 0; + + &:last-child { + margin-right: 0; + } + + &:first-child { + margin-left: 0; + } +} + +.degreesDisplay__degree--tonic { + background-color: var(--note-bg-tonic); + color: var(--note-color-tonic); +} + +.degreesDisplay__degree--mediant { + background-color: var(--note-bg-mediant); + color: var(--note-color-mediant); +} + +.degreesDisplay__degree--dominant { + background-color: var(--note-bg-dominant); + color: var(--note-color-dominant); +} diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.spec.ts b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.spec.ts new file mode 100644 index 0000000..7e58ebb --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.spec.ts @@ -0,0 +1,92 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScaleDegreesComponent } from './scale-degrees.component'; +import { Component, DebugElement } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { ScaleDegreesModule } from './scale-degrees.module'; + +describe('ScaleDegreesComponent', () => { + const selectors = { + tonicBlob: By.css('.tonic'), + mediantBlob: By.css('.mediant'), + dominantBlob: By.css('.dominant') + }; + + const classNames = { + tonicSelected: 'degreesDisplay__degree--tonic', + mediantSelected: 'degreesDisplay__degree--mediant', + dominantSelected: 'degreesDisplay__degree--dominant' + }; + + @Component({ + selector: 'app-scale-degrees-spec', + template: ` + + ` + }) + class ScaleDegreesComponentSpec { + } + + let component: ScaleDegreesComponentSpec; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ScaleDegreesComponentSpec], + imports: [ScaleDegreesModule] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ScaleDegreesComponentSpec); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('clickTonic()', () => { + let tonicBlob: DebugElement; + + beforeEach(() => { + tonicBlob = fixture.debugElement.query(selectors.tonicBlob); + tonicBlob.nativeElement.click(); + fixture.detectChanges(); + }); + + it('removes the active class to the tonic degree display on first click', () => { + expect(tonicBlob.classes[classNames.tonicSelected]).toBeFalsy(); + }); + }); + + xdescribe('clickMediant()', () => { + let mediantBlob: DebugElement; + + beforeEach(() => { + mediantBlob = fixture.debugElement.query(selectors.mediantBlob); + mediantBlob.nativeElement.click(); + fixture.detectChanges(); + }); + + it('adds the active class to the mediant degree display on first click', () => { + expect(mediantBlob.classes[classNames.mediantSelected]).toBeTruthy(); + }); + }); + + xdescribe('clickDominant()', () => { + let dominantBlob: DebugElement; + + beforeEach(() => { + dominantBlob = fixture.debugElement.query(selectors.dominantBlob); + dominantBlob.nativeElement.click(); + fixture.detectChanges(); + }); + + it('adds the active class to the dominant degree display on first click', () => { + expect(dominantBlob.classes[classNames.dominantSelected]).toBeTruthy(); + }); + }); +}); diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.ts b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.ts new file mode 100644 index 0000000..131f401 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.component.ts @@ -0,0 +1,28 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'app-scale-degrees', + templateUrl: './scale-degrees.component.html', + styleUrls: ['./scale-degrees.component.scss'] +}) +export class ScaleDegreesComponent { + @Output() setTonicHighlight = new EventEmitter(); + @Output() setMediantHighlight = new EventEmitter(); + @Output() setDominantHighlight = new EventEmitter(); + @Input() tonicActive; + @Input() mediantActive; + @Input() dominantActive; + + clickTonic() { + this.setTonicHighlight.emit(); + } + + clickMediant() { + this.setMediantHighlight.emit(); + } + + clickDominant() { + this.setDominantHighlight.emit(); + } + +} diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.module.ts b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.module.ts new file mode 100644 index 0000000..517daa8 --- /dev/null +++ b/apps/fretonator-web/src/app/common/fretonator/scale-degrees/scale-degrees.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ScaleDegreesComponent } from './scale-degrees.component'; + + +@NgModule({ + declarations: [ScaleDegreesComponent], + exports: [ + ScaleDegreesComponent + ], + imports: [ + CommonModule + ] +}) +export class ScaleDegreesModule { } diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.html b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.html index 2450083..3e15fd4 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.html +++ b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.html @@ -9,98 +9,5 @@

-
- - -
- - -
-

Degrees

-
- 1 - 3 - 5 -
-
- -
-

About Theoretical Scales - -

-

A theoretical scale or impossible key is a key whose key signature has at least - one double flat (𝄫) or double sharp (x).

-

{{modeDisplayString}} is a theoretical scale and looks unnecessarily complicated. We can - make things simpler!

-

Switch to the enharmonic equivalent note - of {{modeMap[0].displayName | getEnharmonicEquivalent }} to make - the notes easier to read. (It'll sound exactly the same!)

- Switch to {{modeMap[0].displayName | getEnharmonicEquivalent }} - -
- -
-

About Scale Degrees - -

-

- Each of the 7 notes of a mode or scale is called a scale degree, and has a specific name. -

-
    -
  1. Tonic
  2. -
  3. Supertonic
  4. -
  5. Mediant
  6. -
  7. Subdominant
  8. -
  9. Dominant
  10. -
  11. Submediant
  12. -
  13. Leading note
  14. -
-

- Notes 1, 3 and 5 of a scale make up the tonic triad, which is simply a chord of three notes built on - the first note of the scale. This is the the most important chord to learn when jamming as it is the home - chord - meaning it's usually the chord that the jam track starts on and returns to often. -

-

- Scale degrees 1, 3, and 5 are highlighted on the fretboard to give you a helpful point of reference when learning - the mode. -

-
diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.scss b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.scss index 41fbda9..596e616 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.scss +++ b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.scss @@ -13,7 +13,6 @@ @media screen and (min-width: $screen-med) { flex-direction: row; align-items: flex-start; - margin-bottom: pxToRem($grid-unit * 8); } } @@ -31,55 +30,6 @@ } } -.scaleMap__title { - @include info_container_title; -} - -.degreesDisplay { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - height: $infoContainer_info_row_height; -} - -.degreesDisplay__degree { - display: flex; - justify-content: center; - align-items: center; - font-size: pxToRem(16); - height: pxToRem($grid-unit * 4); - width: pxToRem($grid-unit * 4); - border-radius: 50%; - font-weight: var(--font-weight-bold); - font-family: var(--font-family-main); - margin-left: pxToRem($grid-unit); - margin-right: pxToRem($grid-unit); - - &:last-child { - margin-right: 0; - } - - &:first-child { - margin-left: 0; - } -} - -.degreesDisplay__degree--tonic { - background-color: var(--note-bg-tonic); - color: var(--note-color-tonic); -} - -.degreesDisplay__degree--mediant { - background-color: var(--note-bg-mediant); - color: var(--note-color-mediant); -} - -.degreesDisplay__degree--dominant { - background-color: var(--note-bg-dominant); - color: var(--note-color-dominant); -} - .scaleDisplay { display: flex; flex-direction: column; @@ -128,108 +78,9 @@ } } -.buttonRow { - display: flex; - flex-direction: column; - - @media screen and (min-width: $screen-sm) { - flex-direction: row; - } -} - -.button__playScale { - @include chip_button_base(); - margin-top: pxToRem($grid-unit * 2); - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - transition: background-color 0.1s ease-in-out; - - &:hover, &:active { - background-color: var(--purple); - } - - @media screen and (min-width: $screen-sm) { - margin-right: pxToRem($grid-unit * 2); - } - - display: none; -} - -.button__playScale__svg { - display: flex; - height: pxToRem($grid-unit * 2); - width: pxToRem($grid-unit * 2); - margin-right: pxToRem($grid-unit / 2); -} - -.button__infoToggle { - @include chip_button_base(); - border-color: var(--info-toggle-foreground-color); - color: var(--info-toggle-foreground-color); - margin-top: pxToRem($grid-unit * 2); -} - -.infoBlock { - background-color: var(--black); - margin-left: pxToRem($grid-unit * -4); - margin-right: pxToRem($grid-unit * -4); - padding: pxToRem($grid-unit * 4); - margin-bottom: pxToRem($grid-unit * 4); - display: flex; - flex-direction: column; -} - -.infoBlock__title { - @include font_medium; - color: var(--peach); - padding-bottom: pxToRem($grid-unit * 2); - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; -} - -.infoBlock__close { - border-width: 0; - background-color: transparent; - height: pxToRem(44); - width: pxToRem(44); - padding: pxToRem($grid-unit); - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - color: var(--grey); -} - -.infoBlock__copy { - @include font_bodyCopy; - color: var(--offwhite); - margin-top: pxToRem($grid-unit * 2); - margin-bottom: pxToRem($grid-unit * 2); -} - -.infoBlock__list { - -} - -.infoBlock__listItem { - @include font_bodyCopy; - color: var(--yellow); - margin-bottom: pxToRem($grid-unit * 1); -} - .infoHighlight { border-radius: var(--border-radius-chip); padding: pxToRem($grid-unit / 4) pxToRem(9); - color: var(--black); - background-color: var(--peach); -} - -.actionButton { - @include hard_button_base(); - margin-bottom: pxToRem($grid-unit * 2); - align-self: flex-start; + color: var(--info-highlight-color); + background-color: var(--info-highlight-background-color); } diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.spec.ts b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.spec.ts index 72e3345..b58f846 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.spec.ts +++ b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.spec.ts @@ -1,17 +1,10 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ScaleMapComponent } from './scale-map.component'; -import { Component, DebugElement } from '@angular/core'; +import { Component } from '@angular/core'; import { ScaleMapModule } from './scale-map.module'; -import { By } from '@angular/platform-browser'; describe('ScaleMapComponent', () => { - - const selectors = { - toggleScaleInfo: By.css('.button__infoToggle--scaleDegrees'), - scaleMapDegreesInfo: By.css('.infoBlock--scaleDegrees') - }; - @Component({ selector: 'app-scale-map-spec', template: ` @@ -41,23 +34,5 @@ describe('ScaleMapComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); - - describe('toggleScaleMapInfo()', () => { - let toggleScaleButton: DebugElement; - - beforeEach(() => { - toggleScaleButton = fixture.debugElement.query(selectors.toggleScaleInfo); - toggleScaleButton.nativeElement.click(); - fixture.detectChanges(); - }); - - it('should show the scale map info', () => { - expect(fixture.debugElement.query(selectors.scaleMapDegreesInfo)).toBeTruthy(); - }); - - it('should update the text on the toggle button', () => { - expect(toggleScaleButton.nativeElement.textContent.trim()).toBe('Hide info'); - }); - }); }); diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.ts b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.ts index e2362ef..a8f2fed 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.ts +++ b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.component.ts @@ -1,17 +1,5 @@ import { Component, Input } from '@angular/core'; import { Mode, ModeMap } from '../../../util/types'; -import { NotePlaybackService } from '../../playback/note-playback.service'; -import { GlobalService } from '../../../global.service'; - -enum ScaleDegreesToggleText { - hidden = 'What is this?', - visible = 'Hide info' -} - -enum TheoreticalScalesToggleText { - hidden = 'About theoretical scales', - visible = 'Hide info' -} @Component({ selector: 'app-scale-map', @@ -25,32 +13,4 @@ export class ScaleMapComponent { @Input() modeMap: ModeMap; @Input() isTheoretical: boolean; @Input() modeDisplayString: string; - - showScaleMapInfo = false; - showTheoreticalScalesInfo = false; - scaleDegreesToggleText = ScaleDegreesToggleText.hidden; - theoreticalScalesToggleText = TheoreticalScalesToggleText.hidden; - - constructor(public playbackService: NotePlaybackService, - private globalService: GlobalService) { - } - - toggleScaleMapInfo() { - this.showScaleMapInfo = !this.showScaleMapInfo; - this.scaleDegreesToggleText = this.showScaleMapInfo ? ScaleDegreesToggleText.visible : ScaleDegreesToggleText.hidden; - } - - toggleTheoreticalScaleInfo() { - this.showTheoreticalScalesInfo = !this.showTheoreticalScalesInfo; - this.theoreticalScalesToggleText = this.showTheoreticalScalesInfo ? TheoreticalScalesToggleText.visible : TheoreticalScalesToggleText.hidden; - } - - linkClick() { - this.toggleTheoreticalScaleInfo(); - this.globalService.getScrollTarget().scrollIntoView(); - } - - playScale(modeMap: ModeMap) { - this.playbackService.playMode(modeMap); - } } diff --git a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.module.ts b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.module.ts index ce8b4ed..2c35166 100644 --- a/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.module.ts +++ b/apps/fretonator-web/src/app/common/fretonator/scale-map/scale-map.module.ts @@ -2,23 +2,29 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ScaleMapComponent } from './scale-map.component'; import { DisplayScaleDegreesPipe } from './display-scale-degrees.pipe'; -import { GetEnharmonicEquivalentPipe } from './get-enharmonic-equivalent.pipe'; +import { GetEnharmonicEquivalentPipe } from '../get-enharmonic-equivalent.pipe'; import { RouterModule } from '@angular/router'; -import { GetEnharmonicRouterLinkPipe } from './get-enharmonic-router-link.pipe'; +import { GetEnharmonicRouterLinkPipe } from '../get-enharmonic-router-link.pipe'; import { CrossModule } from '../../svgs/cross/cross.module'; import { PlayModule } from '../../svgs/play/play.module'; +import { ScaleDegreesModule } from '../scale-degrees/scale-degrees.module'; @NgModule({ - declarations: [ScaleMapComponent, DisplayScaleDegreesPipe, GetEnharmonicEquivalentPipe, GetEnharmonicRouterLinkPipe], + declarations: [ + ScaleMapComponent, + DisplayScaleDegreesPipe + ], exports: [ - ScaleMapComponent + ScaleMapComponent, + DisplayScaleDegreesPipe ], imports: [ CommonModule, RouterModule, CrossModule, - PlayModule + PlayModule, + ScaleDegreesModule ] }) export class ScaleMapModule { diff --git a/apps/fretonator-web/src/app/common/header/header.component.ts b/apps/fretonator-web/src/app/common/header/header.component.ts index 6f67d4e..7f83c31 100644 --- a/apps/fretonator-web/src/app/common/header/header.component.ts +++ b/apps/fretonator-web/src/app/common/header/header.component.ts @@ -1,5 +1,4 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; -import { ColorModes } from '../../app.component'; import { AbstractDataService } from '../abstract-data/abstract-data.service'; const StorageKeys = { diff --git a/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.html b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.html new file mode 100644 index 0000000..dd8f0e7 --- /dev/null +++ b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.html @@ -0,0 +1,3 @@ + + + diff --git a/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.scss b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.scss new file mode 100644 index 0000000..8e6c40d --- /dev/null +++ b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.scss @@ -0,0 +1,4 @@ +.svg { + height: 100%; + fill: currentColor; +} diff --git a/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.spec.ts b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.spec.ts new file mode 100644 index 0000000..dde9170 --- /dev/null +++ b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChevronRightComponent } from './chevron-right.component'; + +describe('ChevronRightComponent', () => { + let component: ChevronRightComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ChevronRightComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ChevronRightComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.ts b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.ts new file mode 100644 index 0000000..a6444ac --- /dev/null +++ b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-chevron-right-svg', + templateUrl: './chevron-right.component.html', + styleUrls: ['./chevron-right.component.scss'] +}) +export class ChevronRightComponent { +} diff --git a/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.module.ts b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.module.ts new file mode 100644 index 0000000..c29d31f --- /dev/null +++ b/apps/fretonator-web/src/app/common/svgs/chevron-right/chevron-right.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ChevronRightComponent } from './chevron-right.component'; + + + +@NgModule({ + declarations: [ChevronRightComponent], + exports: [ + ChevronRightComponent + ], + imports: [ + CommonModule + ] +}) +export class ChevronRightModule { } diff --git a/apps/fretonator-web/src/app/common/svgs/moon/moon.module.ts b/apps/fretonator-web/src/app/common/svgs/moon/moon.module.ts index b7926a9..0d4a877 100644 --- a/apps/fretonator-web/src/app/common/svgs/moon/moon.module.ts +++ b/apps/fretonator-web/src/app/common/svgs/moon/moon.module.ts @@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common'; import { MoonComponent } from './moon.component'; - @NgModule({ declarations: [MoonComponent], exports: [ diff --git a/apps/fretonator-web/src/app/common/svgs/sun/sun.module.ts b/apps/fretonator-web/src/app/common/svgs/sun/sun.module.ts index 79b0f0f..8cf23d1 100644 --- a/apps/fretonator-web/src/app/common/svgs/sun/sun.module.ts +++ b/apps/fretonator-web/src/app/common/svgs/sun/sun.module.ts @@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common'; import { SunComponent } from './sun.component'; - @NgModule({ declarations: [SunComponent], exports: [ diff --git a/apps/fretonator-web/src/app/common/video-loader/video-browser/video-browser.component.html b/apps/fretonator-web/src/app/common/video-loader/video-browser/video-browser.component.html index 21fc027..a317668 100644 --- a/apps/fretonator-web/src/app/common/video-loader/video-browser/video-browser.component.html +++ b/apps/fretonator-web/src/app/common/video-loader/video-browser/video-browser.component.html @@ -1,6 +1,6 @@ diff --git a/apps/fretonator-web/src/app/pages/about/about-index/about-index.component.html b/apps/fretonator-web/src/app/pages/about/about-index/about-index.component.html index 904efed..004e920 100644 --- a/apps/fretonator-web/src/app/pages/about/about-index/about-index.component.html +++ b/apps/fretonator-web/src/app/pages/about/about-index/about-index.component.html @@ -15,7 +15,7 @@

Thanks for checking out the Fretonator!

understanding the chord theory behind the modes, and most importantly - having a jam.

The code for the Fretonator is available to view on GitHub and I am gratefully welcoming feedback from musicians, pull requests from software engineers, and anything else you are willing to contribute. diff --git a/apps/fretonator-web/src/app/pages/home/home-index/__snapshots__/home-index.component.spec.ts.snap b/apps/fretonator-web/src/app/pages/home/home-index/__snapshots__/home-index.component.spec.ts.snap index f963f91..e4fda79 100644 --- a/apps/fretonator-web/src/app/pages/home/home-index/__snapshots__/home-index.component.spec.ts.snap +++ b/apps/fretonator-web/src/app/pages/home/home-index/__snapshots__/home-index.component.spec.ts.snap @@ -9,62 +9,8 @@ exports[`HomeIndexComponent should create 1`] = `

- - - How to use the Fretonator - - + Fretonator: the ultimate interactive free guitar theory tool

-
    -
  1. - Choose a starting note -
  2. -
  3. - Pick a mode -
  4. -
  5. - Check out the fretboard -
  6. -
  7. - Have a jam! -
  8. -
  9. - Learn the theory -
  10. -
-
-
- - - - -
@@ -410,6 +314,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="0" + data-highlight="false" data-mode="ionian" data-string="E" data-string-name="e" @@ -420,6 +325,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="subdominant" data-display-note="F" data-fret="1" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -427,6 +333,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -436,6 +343,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="3" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -443,6 +351,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -452,6 +361,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="5" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -459,6 +369,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -468,6 +379,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="7" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -477,6 +389,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="tonic" data-display-note="C" data-fret="8" + data-highlight="true" data-mode="ionian" data-string="E" /> @@ -484,6 +397,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -493,6 +407,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="10" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -500,6 +415,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -509,6 +425,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="12" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -521,6 +438,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="0" + data-highlight="false" data-mode="ionian" data-string="B" data-string-name="B" @@ -531,6 +449,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="tonic" data-display-note="C" data-fret="1" + data-highlight="true" data-mode="ionian" data-string="B" /> @@ -538,6 +457,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -547,6 +467,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="3" + data-highlight="false" data-mode="ionian" data-string="B" /> @@ -554,6 +475,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -563,6 +485,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="5" + data-highlight="false" data-mode="ionian" data-string="B" /> @@ -572,6 +495,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="subdominant" data-display-note="F" data-fret="6" + data-highlight="false" data-mode="ionian" data-string="B" /> @@ -579,6 +503,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -588,6 +513,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="8" + data-highlight="false" data-mode="ionian" data-string="B" /> @@ -595,6 +521,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -604,6 +531,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="10" + data-highlight="false" data-mode="ionian" data-string="B" /> @@ -611,6 +539,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -620,6 +549,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="12" + data-highlight="false" data-mode="ionian" data-string="B" /> @@ -632,6 +562,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="0" + data-highlight="false" data-mode="ionian" data-string="G" data-string-name="G" @@ -640,6 +571,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -649,6 +581,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="2" + data-highlight="false" data-mode="ionian" data-string="G" /> @@ -656,6 +589,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -665,6 +599,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="4" + data-highlight="false" data-mode="ionian" data-string="G" /> @@ -674,6 +609,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="tonic" data-display-note="C" data-fret="5" + data-highlight="true" data-mode="ionian" data-string="G" /> @@ -681,6 +617,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -690,6 +627,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="7" + data-highlight="false" data-mode="ionian" data-string="G" /> @@ -697,6 +635,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -706,6 +645,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="9" + data-highlight="false" data-mode="ionian" data-string="G" /> @@ -715,6 +655,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="subdominant" data-display-note="F" data-fret="10" + data-highlight="false" data-mode="ionian" data-string="G" /> @@ -722,6 +663,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -731,6 +673,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="12" + data-highlight="false" data-mode="ionian" data-string="G" /> @@ -743,6 +686,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="0" + data-highlight="false" data-mode="ionian" data-string="D" data-string-name="D" @@ -751,6 +695,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -760,6 +705,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="2" + data-highlight="false" data-mode="ionian" data-string="D" /> @@ -769,6 +715,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="subdominant" data-display-note="F" data-fret="3" + data-highlight="false" data-mode="ionian" data-string="D" /> @@ -776,6 +723,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -785,6 +733,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="5" + data-highlight="false" data-mode="ionian" data-string="D" /> @@ -792,6 +741,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -801,6 +751,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="7" + data-highlight="false" data-mode="ionian" data-string="D" /> @@ -808,6 +759,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -817,6 +769,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="9" + data-highlight="false" data-mode="ionian" data-string="D" /> @@ -826,6 +779,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="tonic" data-display-note="C" data-fret="10" + data-highlight="true" data-mode="ionian" data-string="D" /> @@ -833,6 +787,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -842,6 +797,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="12" + data-highlight="false" data-mode="ionian" data-string="D" /> @@ -854,6 +810,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="0" + data-highlight="false" data-mode="ionian" data-string="A" data-string-name="A" @@ -862,6 +819,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -871,6 +829,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="2" + data-highlight="false" data-mode="ionian" data-string="A" /> @@ -880,6 +839,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="tonic" data-display-note="C" data-fret="3" + data-highlight="true" data-mode="ionian" data-string="A" /> @@ -887,6 +847,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -896,6 +857,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="5" + data-highlight="false" data-mode="ionian" data-string="A" /> @@ -903,6 +865,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -912,6 +875,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="7" + data-highlight="false" data-mode="ionian" data-string="A" /> @@ -921,6 +885,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="subdominant" data-display-note="F" data-fret="8" + data-highlight="false" data-mode="ionian" data-string="A" /> @@ -928,6 +893,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -937,6 +903,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="10" + data-highlight="false" data-mode="ionian" data-string="A" /> @@ -944,6 +911,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -953,6 +921,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="12" + data-highlight="false" data-mode="ionian" data-string="A" /> @@ -965,6 +934,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="0" + data-highlight="false" data-mode="ionian" data-string="E" data-string-name="E" @@ -975,6 +945,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="subdominant" data-display-note="F" data-fret="1" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -982,6 +953,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -991,6 +963,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="dominant" data-display-note="G" data-fret="3" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -998,6 +971,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -1007,6 +981,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="submediant" data-display-note="A" data-fret="5" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -1014,6 +989,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -1023,6 +999,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="leadingTone" data-display-note="B" data-fret="7" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -1032,6 +1009,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="tonic" data-display-note="C" data-fret="8" + data-highlight="true" data-mode="ionian" data-string="E" /> @@ -1039,6 +1017,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -1048,6 +1027,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="supertonic" data-display-note="D" data-fret="10" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -1055,6 +1035,7 @@ exports[`HomeIndexComponent should create 1`] = `
@@ -1064,6 +1045,7 @@ exports[`HomeIndexComponent should create 1`] = ` data-degree="mediant" data-display-note="E" data-fret="12" + data-highlight="false" data-mode="ionian" data-string="E" /> @@ -1142,40 +1124,104 @@ exports[`HomeIndexComponent should create 1`] = `
-

- + + + + Highlight scale degrees + + + +

+ + + +
+ +
+ + +
+
+
- -
- - - - - Tap notes on the fretboard for sound! - -

+
+ + +
+
+ + +
+
+ +
+
- @@ -1293,76 +1339,45 @@ exports[`HomeIndexComponent should create 1`] = ` B

-
- - -
-
- -
-

- Degrees -

-
- - 1 - - - 3 - - - 5 - -
-
- - + + +

- How to use the Fretonator - Fretonator: the ultimate interactive free guitar theory tool + Fretonator: the ultimate interactive free guitar theory tool

-
    -
  1. Choose a starting note
  2. -
  3. Pick a mode
  4. -
  5. Check out the fretboard
  6. -
  7. Have a jam!
  8. -
  9. Learn the theory
  10. -
- -
diff --git a/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.scss b/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.scss index e09cfb5..12840c9 100644 --- a/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.scss +++ b/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.scss @@ -3,29 +3,14 @@ @import '../../../../styles/functions'; @import '../../../../styles/typography'; -.hidden { - display: none; -} - .hero { background-color: var(--hero-background-color); display: block; width: 100%; padding-top: pxToRem($grid-unit * 4); padding-bottom: pxToRem($grid-unit * 4); -} - -.hero__grid { - display: flex; - flex-direction: column; - list-style: none; - text-align: center; - padding: 0; - position: relative; - - @media screen and (min-width: $screen-sm) { - flex-direction: row; - } + margin-left: auto; + margin-right: auto; } .hero__title { @@ -39,91 +24,6 @@ text-align: center; font-weight: var(--font-weight-bold); position: relative; - height: pxToRem($grid-unit * 6); - - span { - position: absolute; - right: 0; - text-align: center; - top: 0; - left: 0; - font-weight: var(--font-weight-bold); - } -} - -.hidden { - display: none; -} - -.hero__block { - font-family: var(--font-family-main); - letter-spacing: var(--letter-spacing-display); - font-size: pxToRem(14); - text-transform: uppercase; - text-align: center; - font-weight: var(--font-weight-bold); - padding-top: pxToRem($grid-unit * 2); - padding-left: pxToRem($grid-unit * 2); - padding-right: pxToRem($grid-unit * 2); - padding-bottom: pxToRem($grid-unit * 4); - margin: pxToRem($grid-unit); - box-shadow: 8px 8px 0 0 var(--hero-block-box-shadow-color); - - @media screen and (min-width: $screen-sm) { - flex-basis: 20%; - - &:first-child { - margin-left: pxToRem($grid-unit * 2); - } - - &:last-child { - margin-right: pxToRem($grid-unit * 2); - } - } - - &:before { - content: attr(data-step); - @include hard_button_base(); - box-shadow: 4px 4px 0 0 var(--offwhite); - display: block; - width: pxToRem($grid-unit * 6); - margin: pxToRem($grid-unit * 2) auto pxToRem($grid-unit * 4) auto; - } -} - -.hero__text--step1 { - background-color: var(--hero-block-background-step-1); -} - -.hero__text--step2 { - background-color: var(--hero-block-background-step-2); -} - -.hero__text--step3 { - background-color: var(--hero-block-background-step-3); -} - -.hero__text--step4 { - background-color: var(--hero-block-background-step-4); -} - -.hero__text--step5 { - background-color: var(--hero-block-background-step-5); -} - -.hero__toggleHowTo { - @include chip_button_base(); - margin-left: auto; - margin-right: auto; - display: block; - color: var(--hero-toggle-foreground-color); - background-color: var(--hero-toggle-background-color); - border-color: var(--hero-toggle-foreground-color); - margin-top: pxToRem($grid-unit * 4); - - &:focus { - border-color: transparent; - } } .modeSelector__container { diff --git a/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.spec.ts b/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.spec.ts index 160e883..63c88e2 100644 --- a/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.spec.ts +++ b/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.spec.ts @@ -10,15 +10,6 @@ import { ActivatedRoute } from '@angular/router'; import { of } from 'rxjs'; describe('HomeIndexComponent', () => { - const selectors = { - howToToggle: By.css('.hero__toggleHowTo'), - howToList: By.css('.hero__grid') - }; - - const classNames = { - hideHowTo: 'hidden' - }; - @Component({ selector: 'app-home-index-spec', template: ` @@ -66,12 +57,4 @@ describe('HomeIndexComponent', () => { expect(component).toBeTruthy(); expect(fixture).toMatchSnapshot(); }); - - it('should toggle the how-to section', () => { - const howToToggle = fixture.debugElement.query(selectors.howToToggle); - const howToList = fixture.debugElement.query(selectors.howToList); - howToToggle.nativeElement.click(); - fixture.detectChanges(); - expect(howToList.classes[classNames.hideHowTo]).toBeTruthy(); - }); }); diff --git a/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.ts b/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.ts index bc00272..0730f47 100644 --- a/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.ts +++ b/apps/fretonator-web/src/app/pages/home/home-index/home-index.component.ts @@ -22,7 +22,6 @@ export class HomeIndexComponent implements OnInit, AfterViewInit { mode: Mode = Mode.ionian; modeSelectorObjects = ModeSelectorObjects; octave = Octave; - showHowTo; constructor( private title: Title, @@ -38,18 +37,6 @@ export class HomeIndexComponent implements OnInit, AfterViewInit { ngOnInit(): void { this.activatedRoute.params.subscribe(() => this.onRouteChange()); this.setHomePageMeta(); - - const _showHowTo = this.localStorage.getItem('showHowTo'); - switch (_showHowTo) { - case false: - this.showHowTo = false; - break; - case true: - this.showHowTo = true; - break; - default: - this.showHowTo = true; - } } ngAfterViewInit(): void { @@ -77,11 +64,6 @@ export class HomeIndexComponent implements OnInit, AfterViewInit { this.setHomePageMeta(); } - toggleHowTo() { - this.showHowTo = !this.showHowTo; - this.localStorage.setItem('showHowTo', this.showHowTo); - } - setHomePageMeta() { const pageDescription = this.metaService.generateHomePageMetaDescription(this.note, this.noteExtenderString, this.mode); const pageTitle = this.metaService.generateHomePageTitle(this.note, this.noteExtenderString, this.mode); diff --git a/apps/fretonator-web/src/app/util/constants.ts b/apps/fretonator-web/src/app/util/constants.ts index 09d09ac..4a69c6a 100644 --- a/apps/fretonator-web/src/app/util/constants.ts +++ b/apps/fretonator-web/src/app/util/constants.ts @@ -553,14 +553,24 @@ export const ChordPatterns = { export const Octave = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; -export const ScaleDegrees = [ - 'tonic', - 'supertonic', - 'mediant', - 'subdominant', - 'dominant', - 'submediant', - 'leadingTone' +export enum ScaleDegrees { + tonic = 'tonic', + supertonic = 'supertonic', + mediant = 'mediant', + subdominant = 'subdominant', + dominant = 'dominant', + submediant = 'submediant', + leadingTone = 'leadingTone' +} + +export const ScaleDegreeNames = [ + ScaleDegrees.tonic, + ScaleDegrees.supertonic, + ScaleDegrees.mediant, + ScaleDegrees.subdominant, + ScaleDegrees.dominant, + ScaleDegrees.submediant, + ScaleDegrees.leadingTone ]; export const ModeSelectorObjects = [ diff --git a/apps/fretonator-web/src/app/util/types.ts b/apps/fretonator-web/src/app/util/types.ts index bf4e827..0d71fba 100644 --- a/apps/fretonator-web/src/app/util/types.ts +++ b/apps/fretonator-web/src/app/util/types.ts @@ -1,8 +1,11 @@ +import { ScaleDegrees } from './constants'; + export interface Fret { string: string; fret: number; displayName: string; - degree: string; + degree: ScaleDegrees; + degreeNumber: number; } export enum ChordType { diff --git a/apps/fretonator-web/src/styles.scss b/apps/fretonator-web/src/styles.scss index d4489cc..60aafdf 100644 --- a/apps/fretonator-web/src/styles.scss +++ b/apps/fretonator-web/src/styles.scss @@ -45,9 +45,6 @@ --header-link-color: var(--peach); --hero-background-color: var(--black); --hero-title-color: var(--offwhite-alt); - --hero-block-box-shadow-color: var(--grey); - --hero-toggle-foreground-color: var(--offwhite-alt); - --hero-toggle-background-color: var(--black); --footer-background: var(--black); --footer-border-color: var(--peach); @@ -56,6 +53,9 @@ --footer-title-color: var(--peach); --footer-list-link-color: var(--yellow); --footer-small-button-accent-color: var(--yellow); + + --info-highlight-color: var(--black); + --info-highlight-background-color: var(--peach); } [color-mode="light"] { @@ -72,12 +72,6 @@ --stripe-banner-background: var(--peach); - --hero-block-background-step-1: var(--peach); - --hero-block-background-step-2: var(--yellow); - --hero-block-background-step-3: var(--purple); - --hero-block-background-step-4: var(--turquoise); - --hero-block-background-step-5: var(--blue); - --string-color: var(--black); --string-label-color: var(--black); --nut-color: #1a1a1a; @@ -86,6 +80,7 @@ --fretboard-play-cta-color: var(--grey); --fret-marker-url: url("data:image/svg+xml,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='15' cy='15' r='15' fill='%23dbdae0' /%3E%3C/svg%3E"); + --fretboard-arrow-svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 512 512'%3E%3Cpath fill='%233993dd' d='M319.1 217c20.2 20.2 19.9 53.2-.6 73.7s-53.5 20.8-73.7.6l-190-190c-20.1-20.2-19.8-53.2.7-73.7S109 6.8 129.1 27l190 190z'/%3E%3Cpath fill='%233993dd' d='M319.1 290.5c20.2-20.2 19.9-53.2-.6-73.7s-53.5-20.8-73.7-.6l-190 190c-20.2 20.2-19.9 53.2.6 73.7s53.5 20.8 73.7.6l190-190z'/%3E%3C/svg%3E");; --note-color: var(--yellow); --note-background: var(--black); @@ -140,6 +135,8 @@ --chip-tag-foreground-color: var(--black); --similar-modes-background-color: var(--peach); + + --fretboard-toggle-button-border-color: var(--black); } [color-mode="dark"] { @@ -155,13 +152,6 @@ --text-link-hover-color: #FD7C21; --stripe-banner-background: var(--peach); - - --hero-block-background-step-1: var(--peach); - --hero-block-background-step-2: var(--coral); - --hero-block-background-step-3: var(--mint); - --hero-block-background-step-4: var(--coral); - --hero-block-background-step-5: var(--peach); - --string-color: var(--offwhite-alt); --string-label-color: var(--offwhite-alt); --nut-color: #d3d3d3; @@ -170,6 +160,7 @@ --fretboard-play-cta-color: #d3d3d3; --fret-marker-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Ccircle cx='15' cy='15' r='15' fill='%23474350'/%3E%3C/svg%3E"); + --fretboard-arrow-svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 512 512'%3E%3Cpath fill='%23ee9198' d='M319.1 217c20.2 20.2 19.9 53.2-.6 73.7s-53.5 20.8-73.7.6l-190-190c-20.1-20.2-19.8-53.2.7-73.7S109 6.8 129.1 27l190 190z'/%3E%3Cpath fill='%23ee9198' d='M319.1 290.5c20.2-20.2 19.9-53.2-.6-73.7s-53.5-20.8-73.7-.6l-190 190c-20.2 20.2-19.9 53.2.6 73.7s53.5 20.8 73.7.6l190-190z'/%3E%3C/svg%3E"); --note-color: var(--black); --note-background: var(--offwhite); @@ -224,6 +215,7 @@ --chip-tag-foreground-color: var(--black); --similar-modes-background-color: var(--black); + --fretboard-toggle-button-border-color: var(--peach); } body {